Android 应用程序的启动过程

Android 应用程序的启动过程

ActivityManangerService 再启动一个组件的时候,如果这个组件所在的应用程序还没有启动起来,它就会请求Zygote进程,将这个应用程序启动起来。
Zygote进程通过复制自身的方式来创建一个新的应用程序。由于zygote进程在启动时会在内部创建一个虚拟机实例,因此,通过复制它而得到的应用程序进程就自然得到了一个应用程序实例拷贝。
应用程序进程在启动过程中,还可以获得一个Binder线程池和一个消息循环,

应用程序进程的创建过程

每当ActivityManagerService 需要创建一个新的应用程序来启动一个应用程序组件时,就是通过startProcessLocked 方法向Zygote进程发送一个创建应用程序的请求,

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
    
    try {
        int uid = app.info.uid;
        int[] gids = null;
        try {
            gids = mContext.getPackageManager().getPackageGids(
                    app.info.packageName);
        } catch (PackageManager.NameNotFoundException e) { ... }
        
        
        int pid = Process.start("android.app.ActivityThread",
                mSimpleProcessManagement ? app.processName : null, uid, uid,
                gids, debugFlags, null);
        
    } catch (RuntimeException e) { ... }
}

Process#start

public static final int start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags,
                              String[] zygoteArgs)
{
    if (supportsProcesses()) {  // 判断是否支持支持Binder进程间通信
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) { ... }
    } else {
        // 不支持Binder进程间通信机制,然后创建一个线程来模拟一个应用程序
        ...
    }
}

Process#startViaZygote

private static int startViaZygote(final String processClass,
                              final String niceName,
                              final int uid, final int gid,
                              final int[] gids,
                              int debugFlags,
                              String[] extraArgs)
                              throws ZygoteStartFailedEx {
    int pid;
    synchronized(Process.class) {
        ArrayList<String> argsForZygote = new ArrayList<String>();

        // --runtime-init, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-init");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);

        //TODO optionally enable debuger
        //argsForZygote.add("--enable-debugger");

        // --setgroups is a comma-separated list
        if (gids != null && gids.length > 0) {
            StringBuilder sb = new StringBuilder();
            sb.append("--setgroups=");

            int sz = gids.length;
            for (int i = 0; i < sz; i++) {
                if (i != 0) {
                    sb.append(',');
                }
                sb.append(gids[i]);
            }

            argsForZygote.add(sb.toString());
        }

        if (niceName != null) {
            argsForZygote.add("--nice-name=" + niceName);
        }

        argsForZygote.add(processClass);

        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }
        
        pid = zygoteSendArgsAndGetPid(argsForZygote);
    }

    return pid;
}

Process#zygoteSendArgsAndGetPid
向 zygote 进程发送一个参数列表,该进程启动一个新子进程并返回该子进程的 pid。

private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
        throws ZygoteStartFailedEx {

    int pid;
    // 创建一个连接到Zygote进程的LocalSocket对象
    openZygoteSocketIfNeeded();

    try {
        // 将启动参数传递给Zygote进程
        sZygoteWriter.write(Integer.toString(args.size()));
        sZygoteWriter.newLine();

        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            
            sZygoteWriter.write(arg);
            sZygoteWriter.newLine();
        }

        sZygoteWriter.flush();

        // Should there be a timeout on this?
        pid = sZygoteInputStream.readInt();

        ...
    } catch (IOException ex) { ... }

    return pid;
}

ZygoteInit#runSelectLoopMode
Zygote进程在启动完成之后,会在一个名称为“zygote” 的Socket上等待ActivityManagerService 向它发送创建新的应用程序进程的请求。因此,这一步执行完成之后,Zygote进程就会在ZygoteInit类的静态成员函数runSelectLoopMode中接受到一个创建新的应用程序进程的请求

 private static void runSelectLoopMode() throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList();
        ArrayList<ZygoteConnection> peers = new ArrayList();
        FileDescriptor[] fdArray = new FileDescriptor[4];

        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        int loopCount = GC_LOOP_COUNT;
        while (true) {
            int index;


            try {
                fdArray = fds.toArray(fdArray);
                index = selectReadable(fdArray);
            } catch (IOException ex) {
                throw new RuntimeException("Error in select()", ex);
            }

            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer();
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done;
                done = peers.get(index).runOnce();

                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }
    }

ZygoteConnection # runOnce

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        // 获取创建的应用程序进程的启动参数
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        ...
    }

    ...

    int pid;

    try {
        parsedArgs = new Arguments(args);

        ...

        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    }

    if (pid == 0) {
        // in child
        handleChildProc(parsedArgs, descriptors, newStderr);
        // should never happen
        return true;
    } 
}

ZygoteConnection # handleChildProc
通过调用handleChildProc来启动这个子进程

   private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
        // 存在参数 “--runtime-init” 参数
        if (parsedArgs.runtimeInit) {
            RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
        } else {
            ...
        }
    }

RuntimeInit # zygoteInit

 public static final void zygoteInit(String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {

        commonInit();
        // 启动一个Binder线程池
        zygoteInitNative();

        // 启动ActivityThread类的main函数中
        invokeStaticMain(startClass, startArgs);
    }

Binder线程池的启动过程

RuntimeInit类的zygoteInitNative的函数来启动一个Binder线程池

RuntimeInit # zygoteInitNative

public static final native void zygoteInitNative();

AndroidRuntime # com_android_internal_os_RuntimeInit_zygoteInit

static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

app_main.cpp # onZygoteInit

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        if (proc->supportsProcesses()) {
            LOGV("App process: starting thread pool.\n");
            proc->startThreadPool();
        }       
    }

ProcessState # startThreadPool

sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;
    
    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // mmap binder,提供一块虚拟地址空间来接收事务。
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
    }
}

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    // 每个支持Binder进程间通信机制的进程内部,只会启动一个Binder线程池,
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
        char buf[32];
        
        sp<Thread> t = new PoolThread(isMain);
        t->run(buf);
    }
}

class PoolThread : public Thread
{
    
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    
    const bool mIsMain;
};

消息循环的创建过程

ActivityThread 的 main 函数中,会创建一个消息循环

    public static final void main(String[] args) {
        
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        Looper.loop();

        thread.detach();
    }

转载

原作者:海在路上
链接:https://www.jianshu.com/p/dd11296215d1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值