从Activity的启动细窥BinderIPC(2)

来源:互联网 发布:大数据产业园规划 编辑:程序博客网 时间:2024/05/17 03:07

上次的源码分析出现了一个runOnce()函数,实际的孵化过程其实是在runOnce()里面,本文章我们再来看看这个函数的源代码

  boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {  //...  try {  //就是这个神奇的函数封装了孵化的过程,成功后就获得新进程的pid了      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,              parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,              parsedArgs.niceName);  }   //...  try {      //这里就是一些异常的处理,可以直接对异常逃逸到main()函数      if (pid == 0) {          // in child          IoUtils.closeQuietly(serverPipeFd);          serverPipeFd = null;          //handleChildProc是一个很重要的函数,在该函数里使用了异常进行逃逸          handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);          //...        } else {         //...       }  } finally {       //...  }}

至于forkAndSpecialize()方法,它实质上调用的一个本地方法nativeForkAndSpecialize(),这个函数实现用C++实现,可以对内核进行调用,在C++代码中,有个叫Dalvik_dalvik_system_Zygote_forkAndSpecialize()的函数,这个函数再调用forkAndSpecializeCommon()函数,然后就直接调用内核的fork系统调用创建一个新进程了。
还是来看看第一个函数调用的代码
说明:u4是一个指向从java层传过来的参数的指针,已经被dvm转换为运行在虚拟机的c++对象了,垃圾回收以及内存管理都按照dvm舒服的处理方式。
JValue* pResult是c++函数调用的结果。

static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args,    JValue* pResult){    pid_t pid;    //还是调用这个函数                                                                                                                                         pid = forkAndSpecializeCommon(args, false);                                                                                                                             RETURN_INT(pid);}

至于forkAndSpecializeCommon()函数,它的功能主要就是拿到fork的系统调用了,代码在dalvik_system_Zygote.c文件中
看看这个函数的实现代码:

static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){    //uid,gid来自java层的参数parsedArgs.uid, parsedArgs.gid,都是从    //ActivityManagerService发送过来的请求     //java层传过来的参数都会根据在参数列表中顺序保存在u4指向的这个数组    pid_t pid;    uid_t uid = (uid_t) args[0];    gid_t gid = (gid_t) args[1];    ArrayObject* gids = (ArrayObject *)args[2];    u4 debugFlags = args[3];    ArrayObject *rlimits = (ArrayObject *)args[4];    int64_t permittedCapabilities, effectiveCapabilities;    if (isSystemServer) {        /*         * Don't use GET_ARG_LONG here for now.  gcc is generating code         * that uses register d8 as a temporary, and that's coming out         * scrambled in the child process.  b/3138621         */        //permittedCapabilities = GET_ARG_LONG(args, 5);        //effectiveCapabilities = GET_ARG_LONG(args, 7);        permittedCapabilities = args[5] | (int64_t) args[6] << 32;        effectiveCapabilities = args[7] | (int64_t) args[8] << 32;    } else {        permittedCapabilities = effectiveCapabilities = 0;    }   //在进程被创建出来后,gDvm.zygote会设为false,表示不是zygote进程,只有一个原来的版本啊,不能迭代fork   //当然子进程中为false,在父进程即zygote进程gDvm.zygote还是保持true,还得继续fork给其他的app使用    if (!gDvm.zygote) {        ......        return -1;    }    //......这里就进行了fork的系统调用啦    pid = fork();    //下面就是一些异常处理    if (pid == 0) {        int err;        err = setgroupsIntarray(gids);        err = setrlimitsFromArray(rlimits);        err = setgid(gid);        err = setuid(uid);        //......        err = setCapabilities(permittedCapabilities, effectiveCapabilities);        //......        enableDebugFeatures(debugFlags);        //......        gDvm.zygote = false;        if (!dvmInitAfterZygote()) {            //......            dvmAbort();        }    } else if (pid > 0) {        /* the parent process */    }    //最后返回的是fork进程的pid    return pid;}     

好咯,现在app的一个进程已经产生,实质为一个dalvik进程,继续看callstack(就是android的调用栈),可以发现在这个进程上调用了activity Thread的main方法,这是一个native的调用,不要忘了还要告诉ActivityManagerService一声app的进程已经建立,你就不用操心啦。同时ActivityManagerService会保留一个activity的代理对象(proxy),它的本质就是一个智能指针,里面封装了app在dalvik进程实例的内存数据(说到代理,就多说两句,binderIPC机制的server跟client间通信也是通过代理来成事,不过是同时实现manager的一个接口获取IBinder,即binder的一个智能指针,再通过binder封装远程调用的函数的函数参数以及返回值信息,顺便实现onTransact()的回调,kernel层也是通过binder driver通过内核空间的内存共享实现,这就是经典的RPC的套路),ActivityManagerService这下就可以控制我们的app啦,包括我们的task,backstack之类的(这些简单的东西就不多说了),下面就是创造一个activity来进入app咯,也是ActivityManagerService来完成,按activity的生命周期一次执行oncreate(),onStart()等方法,当然中间免不了建立main Thraed,并通过looper.mylooper()方法建立主线程的消息循环,接受消息加载activity的类,构造activity的rootViewGroup等消息。就是在栈中看到的关于looper,handler之类的调用咯,所以主线程就不劳烦我们自己创建looper啦。

0 0
原创粉丝点击