Android进程

来源:互联网 发布:ubuntu veloview 编辑:程序博客网 时间:2024/06/07 15:48

  • 概述
  • 1. Process.start
  • 2. startViaZygote
  • 3. zygoteSendArgsAndGetResult
  • 4. runSelectLoop
  • 5. runOnce
  • 6. forkAndSpecialize
    • 6-1 preFork
    • 6-2 nativeForkAndSpecialize
    • 6-3 postForkCommon
    • forkAndSpecialize小结
  • 7. handleChildProc
  • 8. zygoteInit
  • 9. commonInit
  • 10. nativeZygoteInit
  • 11. applicationInit
  • 12. invokeStaticMain
  • 13. MethodAndArgsCaller
  • 总结

基于Android 6.0的源码剖析, 分析Android进程是如何一步步创建的,本文涉及到的源码:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/frameworks/base/core/java/android/os/Process.java
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
 
/frameworks/base/core/java/com/android/internal/os/Zygote.java
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
 
/frameworks/base/cmds/app_process/App_main.cpp (内含AppRuntime类)
/frameworks/base/core/jni/AndroidRuntime.cpp
 
/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
/art/runtime/native/dalvik_system_ZygoteHooks.cc
/art/runtime/Runtime.cc
/art/runtime/Thread.cc
/art/runtime/signal_catcher.cc

概述

本文要介绍的是进程的创建,先简单说说进程与线程的区别。

进程:每个App在启动前必须先创建一个进程,该进程是由Zygote fork出来的,进程具有独立的资源空间,用于承载App上运行的各种Activity/Service等组件。进程对于上层应用来说是完全透明的,这也是google有意为之,让App程序都是运行在Android Runtime。大多数情况一个App就运行在一个进程中,除非在AndroidManifest.xml中配置Android:process属性,或通过native代码fork进程。

线程:线程对应用开发者来说非常熟悉,比如每次new Thread().start()都会创建一个新的线程,该线程并没有自己独立的地址空间,而是与其所在进程之间资源共享。从Linux角度来说进程与线程都是一个task_struct结构体,除了是否共享资源外,并没有其他本质的区别。

对于大多数的应用开发者来说创建线程比较熟悉,而对于创建进程并没有太多的概念。对于系统工程师或者高级开发者,还是有很必要了解Android系统是如何一步步地创建出一个进程的。先来看一张进程创建过程的简要图:

start_app_process

图解:

  1. App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程;
  2. system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求;
  3. zygote进程:在执行ZygoteInit.main()后便进入runSelectLoop()循环体内,当有客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程;
  4. 新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法。

可能朋友不是很了解system_server进程和Zygote进程,下面简要说说:

  • system_server进程:是用于管理整个Java framework层,包含ActivityManager,PowerManager等各种系统服务;
  • Zygote进程:是Android系统的首个Java进程,Zygote是所有Java进程的父进程,包括 system_server进程以及所有的App进程都是Zygote的子进程,注意这里说的是子进程,而非子线程。

如果想更进一步了解system_server进程和Zygote进程在整个Android系统所处的地位,可查看我的另一个文章Android系统-开篇。

接下来从Android 6.0源码,展开讲解进程创建是一个怎样的过程。

1. Process.start

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
publicstatic final ProcessStartResult start(finalString processClass,
                              finalString niceName,
                              intuid,int gid,int[]gids,
                              intdebugFlags,int mountExternal,
                              inttargetSdkVersion,
                              StringseInfo,
                              Stringabi,
                              StringinstructionSet,
                              StringappDataDir,
                              String[]zygoteArgs){
    try{
        //【见流程2】
        returnstartViaZygote(processClass,niceName,uid,gid,gids,
                debugFlags,mountExternal,targetSdkVersion,seInfo,
                abi,instructionSet,appDataDir,zygoteArgs);
    }catch (ZygoteStartFailedExex){
        thrownew RuntimeException("");
    }
}

2. startViaZygote

[-> Process.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
privatestatic ProcessStartResult startViaZygote(finalString processClass,
                              finalString niceName,
                              finalint uid,final int gid,
                              finalint[]gids,
                              intdebugFlags,int mountExternal,
                              inttargetSdkVersion,
                              StringseInfo,
                              Stringabi,
                              StringinstructionSet,
                              StringappDataDir,
                              String[]extraArgs)
                              throwsZygoteStartFailedEx {
    synchronized(Process.class){
        ArrayListargsForZygote = new ArrayList();
 
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid="+ uid);
        argsForZygote.add("--setgid="+ gid);
        argsForZygote.add("--target-sdk-version="+ targetSdkVersion);
 
        if(niceName!= null){
            argsForZygote.add("--nice-name="+ niceName);
        }
        if(appDataDir!= null){
            argsForZygote.add("--app-data-dir="+ appDataDir);
        }
        argsForZygote.add(processClass);
 
        if(extraArgs!= null){
            for(String arg : extraArgs){
                argsForZygote.add(arg);
            }
        }
        //【见流程3】
        returnzygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),argsForZygote);
    }
}

该过程主要工作是生成argsForZygote数组,该数组保存了进程的uid、gid、groups、target-sdk、nice-name等一系列的参数。

3. zygoteSendArgsAndGetResult

[-> Process.java]

Step 3-1. openZygoteSocketIfNeeded

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
privatestatic ZygoteState openZygoteSocketIfNeeded(Stringabi)throws ZygoteStartFailedEx {
    if(primaryZygoteState== null || primaryZygoteState.isClosed()){
        try{
            primaryZygoteState= ZygoteState.connect(ZYGOTE_SOCKET);
        }catch (IOExceptionioe){
            thrownew ZygoteStartFailedEx("Error connecting to primary zygote",ioe);
        }
    }
 
    if(primaryZygoteState.matches(abi)){
        returnprimaryZygoteState;
    }
 
    //当主zygote没能匹配成功,则尝试第二个zygote
    if(secondaryZygoteState== null || secondaryZygoteState.isClosed()){
        try{
        secondaryZygoteState= ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
        }catch (IOExceptionioe){
            thrownew ZygoteStartFailedEx("Error connecting to secondary zygote",ioe);
        }
    }
 
    if(secondaryZygoteState.matches(abi)){
        returnsecondaryZygoteState;
    }
 
    thrownew ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

openZygoteSocketIfNeeded(abi)方法是根据当前的abi来选择与zygote还是zygote64来进行通信。

Step 3-2. zygoteSendArgsAndGetResult

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
privatestatic ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteStatezygoteState,ArrayList args)
        throwsZygoteStartFailedEx {
    try{
        //
        finalBufferedWriter writer = zygoteState.writer;
        finalDataInputStream inputStream = zygoteState.inputStream;
 
        writer.write(Integer.toString(args.size()));
        writer.newLine();
 
        intsz = args.size();
        for(int i = 0;i = 0){
                thrownew ZygoteStartFailedEx(
                        "embedded newlines not allowed");
            }
            writer.write(arg);
            writer.newLine();
        }
 
        writer.flush();
 
        ProcessStartResultresult = new ProcessStartResult();
        //等待socket服务端(即zygote)返回新创建的进程pid;
        //对于等待时长问题,Google正在考虑此处是否应该有一个timeout,但目前是没有的。
        result.pid= inputStream.readInt();
        if(result.pid

这个方法的主要功能是通过socket通道向Zygote进程发送一个参数列表,然后进入阻塞等待状态,直到远端的socket服务端发送回来新创建的进程pid才返回。

既然system_server进程通过socket向Zygote进程发送消息,这是便会唤醒Zygote进程,来响应socket客户端的请求(即system_server端),接下来的操作便是在Zygote进程中执行。

4. runSelectLoop

[–>ZygoteInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
publicstatic void main(Stringargv[]){
    try{
        runSelectLoop(abiList);
        ....
    }catch (MethodAndArgsCallercaller){
        caller.run();//【见流程13】
    }catch (RuntimeExceptionex){
        closeServerSocket();
        throwex;
    }
}

后续会讲到runSelectLoop()方法会抛出异常MethodAndArgsCaller,从而进入caller.run()方法。

[-> ZygoteInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
privatestatic void runSelectLoop(StringabiList)throws MethodAndArgsCaller {
    ...
 
    ArrayListpeers = new ArrayList();
    while(true){
        for(int i = pollFds.length- 1;i >= 0;--i){
            //采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,跳过continue,执行后面的代码
            if((pollFds[i].revents& POLLIN)== 0){
                continue;
            }
            if(i== 0){
                //创建客户端连接
                ZygoteConnectionnewPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            }else {
                //处理客户端数据事务 【见流程5】
                booleandone = peers.get(i).runOnce();
                if(done){
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

没有连接请求时会进入休眠状态,当有创建新进程的连接请求时,唤醒Zygote进程,创建Socket通道ZygoteConnection,然后执行ZygoteConnection的runOnce()方法。

5. runOnce

[-> ZygoteConnection.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
boolean runOnce()throws ZygoteInit.MethodAndArgsCaller{
 
    Stringargs[];
    ArgumentsparsedArgs = null;
    FileDescriptor[]descriptors;
 
    try{
        //读取socket客户端发送过来的参数列表
        args= readArgumentList();
        descriptors= mSocket.getAncillaryFileDescriptors();
    }catch (IOExceptionex){
        closeSocket();
        returntrue;
    }
 
    PrintStreamnewStderr = null;
    if(descriptors!= null & descriptors.length>= 3){
        newStderr= new PrintStream(newFileOutputStream(descriptors[2]));
    }
 
    intpid = -1;
    FileDescriptorchildPipeFd = null;
    FileDescriptorserverPipeFd = null;
 
    try{
        //将binder客户端传递过来的参数,解析成Arguments对象格式
        parsedArgs= new Arguments(args);
        ...
 
        int[]fdsToClose = { -1,-1};
 
        FileDescriptorfd = mSocket.getFileDescriptor();
        if(fd!= null){
            fdsToClose[0]= fd.getInt$();
        }
 
        fd= ZygoteInit.getServerSocketFileDescriptor();
        if(fd!= null){
            fdsToClose[1]= fd.getInt$();
        }
        fd= null;
        【见流程6
        pid= Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,
                parsedArgs.debugFlags,rlimits,parsedArgs.mountExternal,parsedArgs.seInfo,
                parsedArgs.niceName,fdsToClose,parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    }catch (Exceptione){
        ...
    }
 
    try{
        if(pid== 0){
            //子进程执行
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd= null;
            【见流程7
            handleChildProc(parsedArgs,descriptors,childPipeFd,newStderr);
 
            // 不应到达此处,子进程预期的是抛出异常ZygoteInit.MethodAndArgsCaller或者执行exec().
            returntrue;
        }else {
            //父进程执行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd= null;
            returnhandleParentProc(pid,descriptors,serverPipeFd,parsedArgs);
        }
    }finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

6. forkAndSpecialize

[-> Zygote.java]

Java
1
2
3
4
5
6
7
8
9
10
11
publicstatic int forkAndSpecialize(intuid,int gid,int[]gids,int debugFlags,
      int[][]rlimits,int mountExternal,String seInfo,String niceName,int[]fdsToClose,
      StringinstructionSet,String appDataDir){
    VM_HOOKS.preFork(); 【见流程6-1
    intpid = nativeForkAndSpecialize(
              uid,gid,gids,debugFlags,rlimits,mountExternal,seInfo,niceName,fdsToClose,
              instructionSet,appDataDir); 【见流程6-2
    ...
    VM_HOOKS.postForkCommon(); 【见流程6-3
    returnpid;
}

这里VM_HOOKS是做什么的呢?

先说说Zygote进程,如下图:
zygote_sub_thread

从图中可知Zygote进程有4个子线程,分别是ReferenceQueueDaemonFinalizerDaemonFinalizerWatchdogDaemonHeapTaskDaemon,此处称为为Zygote的4个Daemon子线程。图中线程名显示的并不完整是由于底层的进程结构体task_struct是由长度为16的char型数组保存,超过15个字符便会截断。

可能有人会问zygote64进程不是还有system_server,com.android.phone等子线程,怎么会只有4个呢?那是因为这些并不是Zygote子线程,而是Zygote的子进程。在图中用红色圈起来的是进程的VSIZE,virtual size),代表的是进程虚拟地址空间大小。线程与进程的最为本质的区别便是是否共享内存空间,图中VSIZE和Zygote进程相同的才是Zygote的子线程,否则就是Zygote的子进程。

6-1 preFork

[-> ZygoteHooks.java]

Java
1
2
3
4
5
publicvoid preFork(){
    Daemons.stop();//停止4个Daemon子线程【见流程6-1-1】
    waitUntilAllThreadsStopped();//等待所有子线程结束【见流程6-1-2】
    token= nativePreFork();//完成gc堆的初始化工作【见流程6-1-3】
}

Step 6-1-1. Daemons.stop

Java
1
2
3
4
5
6
publicstatic void stop(){
    HeapTaskDaemon.INSTANCE.stop();//Java堆整理线程
    ReferenceQueueDaemon.INSTANCE.stop();//引用队列线程
    FinalizerDaemon.INSTANCE.stop();//析构线程
    FinalizerWatchdogDaemon.INSTANCE.stop();//析构监控线程
}

Step 6-1-2. waitUntilAllThreadsStopped

Java
1
2
3
4
5
6
7
privatestatic void waitUntilAllThreadsStopped(){
    Filetasks = new File("/proc/self/task");
    // 当/proc中线程数大于1,就出让CPU直到只有一个线程,才退出循环
    while(tasks.list().length> 1){
        Thread.yield();
    }
}

Step 6-1-3. nativePreFork

nativePreFork通过JNI最终调用的是dalvik_system_ZygoteHooks.cc中的ZygoteHooks_nativePreFork()方法,如下:

Java
1
2
3
4
5
6
7
8
9
staticjlong ZygoteHooks_nativePreFork(JNIEnv*env,jclass){
    Runtime*runtime = Runtime::Current();
    CHECK(runtime->IsZygote())PreZygoteFork(); 【见流程6-1-3-1
    if(Trace::GetMethodTracingMode()!= TracingMode::kTracingInactive){
      Trace::Pause();
    }
    //将线程转换为long型并保存到token,该过程是非安全的
    returnreinterpret_cast(ThreadForEnv(env));
}

Step 6-1-3-1. PreZygoteFork

Java
1
2
3
4
void Runtime::PreZygoteFork(){
    // 堆的初始化工作。这里就不继续再往下追了,等后续有空专门谢谢关于art虚拟机
    heap_->PreZygoteFork();
}

VM_HOOKS.preFork()的主要功能便是停止Zygote的4个Daemon子线程的运行,等待并确保Zygote是单线程(用于提升fork效率),并等待这些线程的停止,初始化gc堆的工作。

6-2 nativeForkAndSpecialize

nativeForkAndSpecialize()通过JNI最终调用的是com_android_internal_os_Zygote.cpp中的
com_android_internal_os_Zygote_nativeForkAndSpecialize()方法,如下:

[-> com_android_internal_os_Zygote.cpp]

Java
1
2
3
4
5
6
7
8
9
staticjint com_android_internal_os_Zygote_nativeForkAndSpecialize(
    JNIEnv*env,jclass,jint uid,jint gid,jintArray gids,
    jintdebug_flags,jobjectArray rlimits,
    jintmount_external,jstring se_info,jstring se_name,
    jintArrayfdsToClose,jstring instructionSet,jstring appDataDir){
    // 将CAP_WAKE_ALARM赋予蓝牙进程
    jlongcapabilities = 0;
    if(uid== AID_BLUETOOTH){
        capabilities|= (1LL

Step 6-2-1.ForkAndSpecializeCommon

[-> com_android_internal_os_Zygote.cpp]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
staticpid_t ForkAndSpecializeCommon(JNIEnv*env,uid_t uid,gid_t gid,jintArray javaGids,
                                    jint debug_flags,jobjectArray javaRlimits,
                                    jlong permittedCapabilities,jlong effectiveCapabilities,
                                    jint mount_external,
                                    jstring java_se_info,jstring java_se_name,
                                    bool is_system_server,jintArray fdsToClose,
                                    jstring instructionSet,jstring dataDir){
  SetSigChldHandler();//设置子进程的signal信号处理函数
  pid_tpid = fork();//fork子进程 【见流程6-2-1-1】
  if(pid== 0){
    //进入子进程
    DetachDescriptors(env,fdsToClose);//关闭并清除文件描述符
 
    if(!is_system_server){
        //对于非system_server子进程,则创建进程组
        intrc = createProcessGroup(uid,getpid());
    }
    SetGids(env,javaGids);//设置设置group
    SetRLimits(env,javaRlimits);//设置资源limit
 
    intrc = setresgid(gid,gid,gid);
    rc= setresuid(uid,uid,uid);
 
    SetCapabilities(env,permittedCapabilities,effectiveCapabilities);
    SetSchedulerPolicy(env);//设置调度策略
 
    //selinux上下文
    rc= selinux_android_setcontext(uid,is_system_server,se_info_c_str,se_name_c_str);
 
    if(se_info_c_str== NULL & is_system_server){
      se_name_c_str= "system_server";
    }
    if(se_info_c_str!= NULL){
      SetThreadName(se_name_c_str);//设置线程名为system_server,方便调试
    }
    UnsetSigChldHandler();//设置子进程的signal信号处理函数为默认函数
    //等价于调用zygote.callPostForkChildHooks() 【见流程6-2-2-1】
    env->CallStaticVoidMethod(gZygoteClass,gCallPostForkChildHooks,debug_flags,
                              is_system_server? NULL : instructionSet);
    ...
 
  }else if(pid> 0){
    //进入父进程,即Zygote进程
  }
  returnpid;
}

Step 6-2-1-1. fork()

fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次,返回值有3种类型。

  • 父进程中,fork返回新创建的子进程的pid;
  • 子进程中,fork返回0;
  • 当出现错误时,fork返回负数。(当进程数超过上限或者系统内存不足时会出错)

fork()的主要工作是寻找空闲的进程号pid,然后从父进程拷贝进程信息,例如数据段和代码段空间等,当然也包含拷贝fork()代码之后的要执行的代码到新的进程。

下面,说说zygote的fork()过程:

zygote_fork

Zygote进程是所有Android进程的母体,包括system_server进程以及App进程都是由Zygote进程孵化而来。zygote利用fork()方法生成新进程,对于新进程A复用Zygote进程本身的资源,再加上新进程A相关的资源,构成新的应用进程A。何为copy on write(写时复制)?当进程A执行修改某个内存数据时(这便是on write时机),才发生缺页中断,从而分配新的内存地址空间(这便是copy操作),对于copy on write是基于内存页,而不是基于进程的。关于Zygote进程的libc、vm、preloaded classes、preloaded resources是如何生成的,可查看另一个文章Android系统启动-zygote篇。

Step 6-2-2-1. Zygote.callPostForkChildHooks

Java
1
2
3
4
5
6
7
8
9
10
privatestatic void callPostForkChildHooks(intdebugFlags,boolean isSystemServer,
        StringinstructionSet){
    VM_HOOKS.postForkChild(debugFlags,isSystemServer,instructionSet);
}
 
publicvoid postForkChild(intdebugFlags,String instructionSet){
    【见流程6-2-2-1-1
    nativePostForkChild(token,debugFlags,instructionSet);
    Math.setRandomSeedInternal(System.currentTimeMillis());
}

在这里,设置了新进程Random随机数种子为当前系统时间,也就是在进程创建的那一刻就决定了未来随机数的情况,也就是伪随机。

Step 6-2-2-1-1. nativePostForkChild

最终调用dalvik_system_ZygoteHooks的ZygoteHooks_nativePostForkChild

[-> dalvik_system_ZygoteHooks.cc]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
staticvoid ZygoteHooks_nativePostForkChild(JNIEnv*env,jclass,jlong token,jint debug_flags,
                                            jstringinstruction_set){
    Thread*thread = reinterpret_cast(token);
    //设置新进程的主线程id
    thread->InitAfterFork();
    ..
    if(instruction_set!= nullptr){
      ScopedUtfCharsisa_string(env,instruction_set);
      InstructionSetisa = GetInstructionSetFromString(isa_string.c_str());
      Runtime::NativeBridgeActionaction = Runtime::NativeBridgeAction::kUnload;
      if(isa!= kNone & isa != kRuntimeISA){
        action= Runtime::NativeBridgeAction::kInitialize;
      }
      【见流程6-2-2-1-1-1
      Runtime::Current()->DidForkFromZygote(env,action,isa_string.c_str());
    }else {
      Runtime::Current()->DidForkFromZygote(env,Runtime::NativeBridgeAction::kUnload,nullptr);
    }
}

Step 6-2-2-1-1-1. DidForkFromZygote

[-> Runtime.cc]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void Runtime::DidForkFromZygote(JNIEnv*env,NativeBridgeAction action,const char*isa){
  is_zygote_= false;
  if(is_native_bridge_loaded_){
    switch(action){
      caseNativeBridgeAction::kUnload:
        UnloadNativeBridge();//卸载用于跨平台的桥连库
        is_native_bridge_loaded_= false;
        break;
      caseNativeBridgeAction::kInitialize:
        InitializeNativeBridge(env,isa);//初始化用于跨平台的桥连库
        break;
    }
  }
  //创建Java堆处理的线程池
  heap_->CreateThreadPool();
  //重置gc性能数据,以保证进程在创建之前的GCs不会计算到当前app上。
  heap_->ResetGcPerformanceInfo();
  if(jit_.get()== nullptr & jit_options_->UseJIT()){
    //当flag被设置,并且还没有创建JIT时,则创建JIT
    CreateJit();
  }
  //设置信号处理函数
  StartSignalCatcher();
  //启动JDWP线程,当命令debuger的flags指定"suspend=y"时,则暂停runtime
  Dbg::StartJdwp();
}

关于信号处理过程,其代码位于signal_catcher.cc文件中,后续会单独讲解。

6-3 postForkCommon

[-> ZygoteHooks.java]

Java
1
2
3
publicvoid postForkCommon(){
    Daemons.start(); 【见流程6-3-1
}

Step 6-3-1. Daemons.start

Java
1
2
3
4
5
6
publicstatic void start(){
    ReferenceQueueDaemon.INSTANCE.start();
    FinalizerDaemon.INSTANCE.start();
    FinalizerWatchdogDaemon.INSTANCE.start();
    HeapTaskDaemon.INSTANCE.start();
}

VM_HOOKS.postForkCommon的主要功能是在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。

forkAndSpecialize小结

调用关系链:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Zygote.forkAndSpecialize
ZygoteHooks.preFork
Daemons.stop
ZygoteHooks.nativePreFork
dalvik_system_ZygoteHooks.ZygoteHooks_nativePreFork
Runtime::PreZygoteFork
heap_->PreZygoteFork()
Zygote.nativeForkAndSpecialize
com_android_internal_os_Zygote.ForkAndSpecializeCommon
fork()
Zygote.callPostForkChildHooks
ZygoteHooks.postForkChild
dalvik_system_ZygoteHooks.nativePostForkChild
Runtime::DidForkFromZygote
ZygoteHooks.postForkCommon
Daemons.start

时序图:

点击查看大图

fork_and_specialize

到此App进程已完成了创建的所有工作,接下来开始新创建的App进程的工作。在前面ZygoteConnection.runOnce方法中,zygote进程执行完forkAndSpecialize()后,新创建的App进程便进入handleChildProc()方法,下面的操作运行在App进程。

7. handleChildProc

[-> ZygoteConnection.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
privatevoid handleChildProc(ArgumentsparsedArgs,
        FileDescriptor[]descriptors,FileDescriptor pipeFd,PrintStream newStderr)
        throwsZygoteInit.MethodAndArgsCaller{
 
    //关闭Zygote的socket两端的连接
    closeSocket();
    ZygoteInit.closeServerSocket();
 
    if(descriptors!= null){
        try{
            Os.dup2(descriptors[0],STDIN_FILENO);
            Os.dup2(descriptors[1],STDOUT_FILENO);
            Os.dup2(descriptors[2],STDERR_FILENO);
            for(FileDescriptorfd:descriptors){
                IoUtils.closeQuietly(fd);
            }
            newStderr= System.err;
        }catch (ErrnoExceptionex){
            Log.e(TAG,"Error reopening stdio",ex);
        }
    }
 
    if(parsedArgs.niceName!= null){
        //设置进程名
        Process.setArgV0(parsedArgs.niceName);
    }
 
    if(parsedArgs.invokeWith!= null){
        //据说这是用于检测进程内存泄露或溢出时场景而设计,后续还需要进一步分析。
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName,parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd,parsedArgs.remainingArgs);
    }else {
        //执行目标类的main()方法 【见流程8】
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs,null);
    }
}

8. zygoteInit

[–>RuntimeInit.java]

Java
1
2
3
4
5
6
7
8
9
10
publicstatic final void zygoteInit(inttargetSdkVersion,String[]argv,ClassLoader classLoader)
        throwsZygoteInit.MethodAndArgsCaller{
 
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"RuntimeInit");
    redirectLogStreams();//重定向log输出
 
    commonInit();// 通用的一些初始化【见流程9】
    nativeZygoteInit();// zygote初始化 【见流程10】
    applicationInit(targetSdkVersion,argv,classLoader);// 应用初始化【见流程11】
}

9. commonInit

[–>RuntimeInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
privatestatic final void commonInit(){
    // 设置默认的未捕捉异常处理方法
    Thread.setDefaultUncaughtExceptionHandler(newUncaughtHandler());
 
    // 设置市区,中国时区为"Asia/Shanghai"
    TimezoneGetter.setInstance(newTimezoneGetter(){
        @Override
        publicString getId(){
            returnSystemProperties.get("persist.sys.timezone");
        }
    });
    TimeZone.setDefault(null);
 
    //重置log配置
    LogManager.getLogManager().reset();
    newAndroidConfig();
 
    // 设置默认的HTTP User-agent格式,用于 HttpURLConnection。
    StringuserAgent = getDefaultUserAgent();
    System.setProperty("http.agent",userAgent);
 
    // 设置socket的tag,用于网络流量统计
    NetworkManagementSocketTagger.install();
}

默认的HTTP User-agent格式,例如:

Java
1
"Dalvik/1.1.0 (Linux; U; Android 6.0.1;LenovoX3c70 Build/LMY47V)".

10. nativeZygoteInit

nativeZygoteInit()方法在AndroidRuntime.cpp中,进行了jni映射,对应下面的方法。

[–>AndroidRuntime.cpp]

Java
1
2
3
4
staticvoid com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv*env,jobject clazz)
{
    gCurRuntime->onZygoteInit();//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
}

[–>app_main.cpp]

Java
1
2
3
4
5
virtualvoid onZygoteInit()
{
    spproc = ProcessState::self();
    proc->startThreadPool();//启动新binder线程
}

ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),在binder系列文章中的注册服务(addService)详细这两个方法的执行原理。

11. applicationInit

[–>RuntimeInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
privatestatic void applicationInit(inttargetSdkVersion,String[]argv,ClassLoader classLoader)
        throwsZygoteInit.MethodAndArgsCaller{
    //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
    nativeSetExitWithoutCleanup(true);
 
    //设置虚拟机的内存利用率参数值为0.75
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
 
    finalArguments args;
    try{
        args= new Arguments(argv);//解析参数
    }catch (IllegalArgumentExceptionex){
        Slog.e(TAG,ex.getMessage());
        return;
    }
 
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
    //调用startClass的static方法 main() 【见流程12】
    invokeStaticMain(args.startClass,args.startArgs,classLoader);
}

此处args.startClass为”android.app.ActivityThread”。

12. invokeStaticMain

[–>RuntimeInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
privatestatic void invokeStaticMain(StringclassName,String[]argv,ClassLoader classLoader)
        throwsZygoteInit.MethodAndArgsCaller{
    Class>cl;
 
    try{
        cl= Class.forName(className,true,classLoader);
    }catch (ClassNotFoundExceptionex){
        thrownew RuntimeException(
                "Missing class when invoking static main " + className,ex);
    }
 
    Methodm;
    try{
        m= cl.getMethod("main",new Class[]{ String[].class});
    }catch (NoSuchMethodExceptionex){
        thrownew RuntimeException("Missing static main on " + className,ex);
    }catch (SecurityExceptionex){
        thrownew RuntimeException(
                "Problem getting static main on " + className,ex);
    }
 
    intmodifiers = m.getModifiers();
    if(!(Modifier.isStatic(modifiers)& Modifier.isPublic(modifiers))){
        thrownew RuntimeException(
                "Main method is not public and static on " + className);
    }
 
    //通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率。【见流程13】
    thrownew ZygoteInit.MethodAndArgsCaller(m,argv);
}

invokeStaticMain()方法中抛出的异常MethodAndArgsCaller,根据前面的【流程4】中可知,下一步进入caller.run()方法。

13. MethodAndArgsCaller

[–>ZygoteInit.java]

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicstatic class MethodAndArgsCaller extends Exception
        implementsRunnable {
 
    publicvoid run(){
        try{
            //根据传递过来的参数,可知此处通过反射机制调用的是ActivityThread.main()方法
            mMethod.invoke(null,new Object[]{ mArgs });
        }catch (IllegalAccessExceptionex){
            thrownew RuntimeException(ex);
        }catch (InvocationTargetExceptionex){
            Throwablecause = ex.getCause();
            if(causeinstanceof RuntimeException){
                throw(RuntimeException)cause;
            }else if(causeinstanceof Error){
                throw(Error)cause;
            }
            thrownew RuntimeException(ex);
        }
    }
}

到此,总算是进入到了ActivityThread类的main()方法。


总结

当App第一次启动时或者启动远程Service,即AndroidManifest.xml文件中定义了process:remote属性时,都需要创建进程。比如当用户点击桌面的某个App图标,桌面本身是一个app(即Launcher App),那么Launcher所在进程便是这次创建新进程的发起进程,该通过binder发送消息给system_server进程,该进程承载着整个java framework的核心服务。system_server进程从Process.start开始,执行创建进程,流程图(以进程的视角)如下:

点击查看大图

process-create

上图中,system_server进程通过socket IPC通道向zygote进程通信,zygote在fork出新进程后由于fork调用一次,返回两次,即在zygote进程中调用一次,在zygote进程和子进程中各返回一次,从而能进入子进程来执行代码。该调用流程图的过程:

  1. system_server进程即流程1~3):通过Process.start()方法发起创建新进程请求,会先收集各种新进程uid、gid、nice-name等相关的参数,然后通过socket通道发送给zygote进程;
  2. zygote进程即流程4~6):接收到system_server进程发送过来的参数后封装成Arguments对象,图中绿色框forkAndSpecialize()方法是进程创建过程中最为核心的一个环节(详见流程6),其具体工作是依次执行下面的3个方法:
    • preFork():先停止Zygote的4个Daemon子线程(java堆内存整理线程、对线下引用队列线程、析构线程以及监控线程)的运行以及初始化gc堆;
    • nativeForkAndSpecialize():调用linux的fork()出新进程,创建Java堆处理的线程池,重置gc性能数据,设置进程的信号处理函数,启动JDWP线程;
    • postForkCommon():在启动之前被暂停的4个Daemon子线程。
  3. 新进程即流程7~13):进入handleChildProc()方法,设置进程名,打开binder驱动,启动新的binder线程;然后设置art虚拟机参数,再反射调用目标类的main()方法,即Activity.main()方法。
再之后的流程,如果是startActivity则将要进入Activity的onCreate/onStart/onResume等生命周期;如果是startService则将要进入Service的onCreate等生命周期。

0 0
原创粉丝点击