搞懂Android应用启动过程,再也不怕面试官了( 二 )

其中:

  1. openZygoteSocketIfNeeded打开本地socket
  2. zygoteSendArgsAndGetResult发送请求参数,其中带上了ActivityThread类名
  3. return返回的数据结构ProcessStartResult中会有pid字段
梳理一下:
搞懂Android应用启动过程,再也不怕面试官了

文章插图
 
注意:Zygote进程启动时已经创建好了虚拟机实例,所以由他fork出的应用进程可以直接继承过来用而无需创建 。
下面来看Zygote是如何处理socket请求的 。
Zygote处理socket请求从 图解Android系统的启动 一文可知,在ZygoteInit的main函数中,会创建服务端socket 。
//ZygoteInit.javapublic static void main(String argv[]) {//Server类,封装了socketZygoteServer zygoteServer = new ZygoteServer();//创建服务端socket,名字为socketName即zygotezygoteServer.registerServerSocket(socketName);//进入死循环,等待AMS发请求过来zygoteServer.runSelectLoop(abiList);} 【搞懂Android应用启动过程,再也不怕面试官了】看到ZygoteServer 。
//ZygoteServer.javavoid registerServerSocket(String socketName) {int fileDesc;//socket真正的名字被加了个前缀,即 "ANDROID_SOCKET_" + "zygote"final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);//创建文件描述符fdFileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc);//创建LocalServerSocket对象mServerSocket = new LocalServerSocket(fd);}void runSelectLoop(String abiList){//进入死循环while (true) {for (int i = pollFds.length - 1; i >= 0; --i) {if (i == 0) {//...} else {//得到一个连接对象ZygoteConnection,调用他的runOnceboolean done = peers.get(i).runOnce(this);}}}} 来到ZygoteConnection的runOnce 。
boolean runOnce(ZygoteServer zygoteServer){//读取socket请求的参数列表String args[] = readArgumentList();//创建应用进程int pid = Zygote.forkAndSpecialize(...);if (pid == 0) {//如果是应用进程(Zygote fork出来的子进程),处理请求参数handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);return true;} else {return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} handleChildProc方法调用了ZygoteInit的zygoteInit方法,里边主要做了3件事:
  1. 启动binder线程池(后面分析)
  2. 读取请求参数拿到ActivityThread类并执行他的main函数,执行thread.attach告知AMS并回传自己的binder句柄
  3. 执行Looper.loop()启动消息循环(代码前面有)
这样应用进程就启动起来了 。梳理一下:
搞懂Android应用启动过程,再也不怕面试官了

文章插图
 
下面看下binder线程池是怎么启动的 。
启动binder线程池Zygote的跨进程通信没有使用binder,而是socket,所以应用进程的binder机制不是继承而来,而是进程创建后自己启动的 。
前边可知,Zygote收到socket请求后会得到一个ZygoteConnection,他的runOnce会调用handleChildProc 。
//ZygoteConnection.javaprivate void handleChildProc(...){ZygoteInit.zygoteInit(...);}//ZygoteInit.javapublic static final void zygoteInit(...){RuntimeInit.commonInit();//进入native层ZygoteInit.nativeZygoteInit();RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);} 来到AndroidRuntime.cpp:
//AndroidRuntime.cppstatic void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz){gCurRuntime->onZygoteInit();} 来到app_main.cpp:
//app_main.cppvirtual void onZygoteInit() {//获取单例sp<ProcessState> proc = ProcessState::self();//在这里启动了binder线程池proc->startThreadPool();} 看下ProcessState.cpp:
//ProcessState.cppsp<ProcessState> ProcessState::self(){//单例模式,返回ProcessState对象if (gProcess != NULL) {return gProcess;}gProcess = new ProcessState("/dev/binder");return gProcess;}//ProcessState构造函数ProcessState::ProcessState(const char *driver): mDriverName(String8(driver)), mDriverFD(open_driver(driver)) //打开binder驱动,//...{if (mDriverFD >= 0) {//mmap是一种内存映射文件的方法,把mDriverFD映射到当前的内存空间mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);}}//启动了binder线程池void ProcessState::startThreadPool(){if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}}void ProcessState::spawnPooledThread(bool isMain){if (mThreadPoolStarted) {//创建线程名字"Binder:${pid}_${自增数字}"String8 name = makeBinderThreadName();sp<Thread> t = new PoolThread(isMain);//运行binder线程t->run(name.string());}} ProcessState有两个宏定义值得注意一下:


推荐阅读