安卓应用启动流程

6

我正在搜索关于如何在安卓上启动应用程序的信息。我想找到关于Zygote和fork()的有用信息。您知道一些有用的网站或书籍吗?


实际问题是什么?活动是通过“startActivity”启动的。如果您想深入了解Android如何处理进程,最好搜索“Linux内核”,而不是Android :) - poitroae
我想了解Android应用程序是如何启动的。类似于这篇文章http://multi-core-dump.blogspot.com/2010/04/android-application-launch.html,但需要更详细的说明。 - Aprel
3个回答

17

2

这份演示文稿中有一个很好的解释。它部分用韩语书写,但大部分信息都是用英语表达。


谢谢,非常好。还有一些关于kandroid.org的文档,但是是韩文的。你知道其他一些英文内容相同的网站吗? - Aprel
抱歉,但不行。我不知道。韩国人在Android操作系统开发方面非常擅长。有时我会发现所需的信息只有韩文(翻译工具帮了我 :))。 - Yury

0

这里是与编程有关的文本,基于AOSP 9.0.0的简明(流程非常复杂,所以即使是简明版也不会很短)而精确的答案。

每个Android Java进程都是从Zygote分叉出来的,因此首先介绍一下Zygote如何启动。

init进程是linux中的第一个进程,它启动了可执行文件"app_process",其内部实现如下:

(entry point of app_process)int main
    ->void AndroidRuntime::start
        startVm    //start Java VM
        startReg    //register common native functions
        //call java method ZygoteInit.main from native code
        env->CallStaticVoidMethod  

然后这里是最重要的Java方法:ZygoteInit.main,我们从上面的本地代码“env->CallStaticVoidMethod”到达此处。

当您在主Activity的onCreate中设置断点并开始调试应用程序并在那里中断时,这也是调用堆栈中的第一个方法。但实际上您的应用程序从未到达ZygoteInit.main的开头,它仅在app_process(或称为Zygote)中从头执行。

//Java code
->ZygoteInit.main  
    //Android application never get here(the beginning)
    //start system server process which contains AMS/WMS,etc
    forkSystemServer  

    //for Zygote, runSelectLoop never return
    //for Android application, runSelectLoop returns a Runnable 
    //whose run() method will just execute ActivityThread.main 
    //which is considered as the real main entry of Android application
    //since it contains the message loop
    caller = zygoteServer.runSelectLoop
    ->zygoteServer.runSelectLoop
        //this is the main loop of Zygote who is a 
        //server that receive process-creating requests
        //from client processes and fork them
        loop forever

            //Zygote wait here for other process's requests to start new Java process
            Os.poll(pollFds, -1);

            //after wake up upon requests arrive, process the request
            final Runnable command = connection.processOneCommand(this);
            ->ZygoteConnection.processOneCommand
                 read and parse process-start request command from client process

                 //the native linux fork() is executed in this methdod
                 //after it returns, we can decide which process we are in 
                 //from pid's value just like the native fork()
                 pid = Zygote.forkAndSpecialize

                 //if in child                        
                 return handleChildProc
                 ->ZygoteConnection.handleChildProc
                     return ZygoteInit.zygoteInit
                     ->ZygoteInit.zygoteInit
                         RuntimeInit.commonInit();
                         ZygoteInit.nativeZygoteInit();//JNI method
                             //native code
                             ->AppRuntime::onZygoteInit()
                                 sp<ProcessState> proc = ProcessState::self();
                                 //starting thread pool which contains binder threads
                                 proc->startThreadPool();
                         return RuntimeInit.applicationInit
                         ->RuntimeInit.applicationInit
                             return findStaticMain
                             ->RuntimeInit.findStaticMain
                                 //MethodAndArgsCaller is a Runnable, 
                                 //whose run() is constructed so that 
                                 //it just call ActivityThread.main()
                                 //it is ActivityThread since there is a string parameter 
                                 //whose content is "android.app.ActivityThread" from the client process's request
                                 return new MethodAndArgsCaller
                 //if in parent process i.e. Zygote
                 return null

            //if in forked child process
            return command;
            //if in parent process i.e. Zygote
            continue to run the loop

    //Zygote never get here
    //for Android application, now caller contains a MethodAndArgsCaller which is a Runnable
    //whose run() calls ActivityThread.main and never return
    //since ActivityThread.main runs the main message loop        
    caller.run();

当您启动一个Activity时,最终会进入Activity Manager Service(AMS,位于系统服务器进程中)。如果尚未为该Activity创建进程,则AMS将向Zygote服务器发送进程启动请求(在上面描述的zygote进程中启动,由init进程启动),该过程如下:

//in AMS (system server process)
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(....,entryPoint, ....);
->startProcessLocked        
    ->Process.start
        ->ZygoteProcess.start
            ->ZygoteProcess.startViaZygote
                ->ZygoteProcess.zygoteSendArgsAndGetResult
                    //send the request to Zygote server through sockets
                    //note that "android.app.ActivityThread" is send to Zygote server as a parameter

此时,上述列出的Zygote代码将会被唤醒。

Os.poll(pollFds, -1);

并且分叉子进程后,父进程即Zygote将再次执行轮询等待下一个请求,而分叉的子进程将从runSelectLoop返回并执行上述代码列表中描述的ActivityThread.main。

因此,新进程的确切入口点将在Zygote.forkAndSpecialize中的本地fork()深处之后,在一个名为ForkAndSpecializeCommon的本地函数中,然后一直通过返回路径上升到

caller = zygoteServer.runSelectLoop

在ZygoteInit.main中。因此,尽管Android应用程序的调用堆栈从ZygoteInit.main开始,但在ZygoteInit.main中执行的代码始于对runSelectLoop的调用,而不是ZygoteInit.main的开头。

关于Activity:实际上,Activity与入口点或启动过程无关。当AMS随时向进程发送Activity-start请求时,Activity就会启动。因此,Activity启动进程始于主消息循环接收到启动请求时,由AMS的消息驱动,并且完全解耦于应用程序启动过程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接