ActivityManagerService启动新的process过程分析

 

 We need start a new process when we tap application launcher or start a new service which is in a different process. This artical will describe how a new process is created but no matter whoever the caller is.

1.startProcessLocked in ActivityManagerService.java
        Ignore rest of the function and focus on below code.

  1.             int pid = Process.start("android.app.ActivityThread",
  2.                     mSimpleProcessManagement ? app.processName : null, uid, uid,
  3.                     gids, debugFlags, null);  
复制代码



        According to above code,we can find that another process created with a nice name "app.processName" or NULL where the first args is the first class started by the new process.

        Now, we look into the start function of the Process class.

2.startViaZygote in Process.java

  1.             argsForZygote.add("--runtime-init");
  2.             argsForZygote.add("--setuid=" + uid);
  3.             argsForZygote.add("--setgid=" + gid);
复制代码



        The first sentence means that we need to init runtime when create this Process, the purpose of this initialization will be discussed later.
        We should know the communication between ActivityManagerService and  zygote relies on socket, AM writes the arguments of the new process into the buffer for zygote socket.
        Then the starter's work is done, let's turn over into the zygote at looked at the other socket communication side.

3.
        The zygote process will be in a loop in order to detect any connect into the zygote socket and fork the request process after being started by init deamon process, all this work is running in function runSelectLoopMode in ZygoteInit.java and calls runOnce function in ZygoteConnection.java to fork new process.

4.runOnce in ZygoteConnection.java

   
  1.          pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
  2.                     parsedArgs.gids, parsedArgs.debugFlags, rlimits);
复制代码



        Above code forks a new process, It is very easy to understand and  unnecessary to look into.

      
  1.   if (pid == 0) {
  2.             // in child
  3.             handleChildProc(parsedArgs, descriptors, newStderr);
  4.             // should never happen
  5.             return true;
  6.         } else { /* pid != 0 */
  7.             // in parent...pid of < 0 means failure
  8.             return handleParentProc(pid, descriptors, parsedArgs);
  9.         }  
复制代码

      

        As we know, parent process and child process will execute the code simultaneously after fork operation, therefore, the parent process will get the real pid of child process and call handleParentProc method, meanwhile, the child process will get a zero pid value and call handleChildProc.
        We ignore the handleParentProc in which there is nothing important but cleanup of parent process.

The belowing operations are in the new process.

5.handleChildProc in ZygoteConnection.java

        Function handleChildProc will check if the process starter needs the runtime initialization which is set in step 2. Here need to init runtime while every process is being created.

      
  1. if (parsedArgs.runtimeInit) {
  2.             RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
  3.         }
复制代码

        

6.zygoteInit in RuntimeInit.java

   
  1. public static final void zygoteInit(String[] argv)
  2.             throws ZygoteInit.MethodAndArgsCaller {
  3.         // TODO: Doing this here works, but it seems kind of arbitrary. Find
  4.         // a better place. The goal is to set it up for applications, but not
  5.         // tools like am.
  6.         System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
  7.         System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));

  8.         commonInit();
  9.         zygoteInitNative();

  10.         int curArg = 0;
  11.         for ( /* curArg */ ; curArg < argv.length; curArg++) {
  12.             String arg = argv[curArg];

  13.             if (arg.equals("--")) {
  14.                 curArg++;
  15.                 break;
  16.             } else if (!arg.startsWith("--")) {
  17.                 break;
  18.             } else if (arg.startsWith("--nice-name=")) {
  19.                 String niceName = arg.substring(arg.indexOf('=') + 1);
  20.                 Process.setArgV0(niceName);
  21.             }
  22.         }

  23.         if (curArg == argv.length) {
  24.             Slog.e(TAG, "Missing classname argument to RuntimeInit!");
  25.             // let the process exit
  26.             return;
  27.         }

  28.         // Remaining arguments are passed to the start class's static main

  29.         String startClass = argv[curArg++];
  30.         String[] startArgs = new String[argv.length - curArg];

  31.         System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
  32.         invokeStaticMain(startClass, startArgs);
  33.     }
复制代码



6.1 zygoteInitNative
        This function is a native function which spawns a pool thread to detect binder IPCs. Its prototype in JNI layer is underlying:

  1. static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
  2. {
  3.     gCurRuntime->onZygoteInit();
  4. }
复制代码


        gCurRuntime is a global variable which is initialized when app_main starts. We can find this process in AndroidRuntime constructor. So we confirm that the gCurRuntime is an AppRuntime instance and class AppRuntime extends AndroidRuntime.According to all the facts, we can conclude the onZygoteInit function belongs to class AppRuntime.
   
  1. virtual void onZygoteInit()
  2.     {
  3.         sp<ProcessState> proc = ProcessState::self();
  4.         if (proc->supportsProcesses()) {
  5.             LOGV("App process: starting thread pool.\n");
  6.             proc->startThreadPool();
  7.         }      
  8.     }
复制代码



6.2 invokeStaticMain

After creating process and corresponding pool thread for binder IPC, the last job here is to call the "main" method of the process's first class. It should be "android.app.ActivityThread" for AM to start a new activity or service of different processes.
ActivityThread instance is the main thread of the new process.

7.main method in ActivityThread.java
   
  1. public static final void main(String[] args) {
  2.         SamplingProfilerIntegration.start();

  3.         Process.setArgV0("<pre-initialized>");

  4.         Looper.prepareMainLooper();
  5.         if (sMainThreadHandler == null) {
  6.             sMainThreadHandler = new Handler();
  7.         }

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

  10.         if (false) {
  11.             Looper.myLooper().setMessageLogging(new
  12.                     LogPrinter(Log.DEBUG, "ActivityThread"));
  13.         }

  14.         Looper.loop();

  15.         if (Process.supportsProcesses()) {
  16.             throw new RuntimeException("Main thread loop unexpectedly exited");
  17.         }

  18.         thread.detach();
  19.         String name = (thread.mInitialApplication != null)
  20.             ? thread.mInitialApplication.getPackageName()
  21.             : "<unknown>";
  22.         Slog.i(TAG, "Main thread of " + name + " is now exiting");
  23.     }
  24. }
复制代码



In above code, we can not find any sentence create the new activity or service. where is the operation hiding?

The implementation is very complicated, the above code has a sentence "thread.attach(false)" where all the stuff is hiding.

I will discuss how activity starts in later artical.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值