卷二 Dalvik与Android源码分析 第二章 进程与线程 2.1 Dalvik虚拟机的进程创建机制 图书版试读--请勿转发

作者 [email protected]


2 进程与线程



2.1 Dalvik虚拟机的进程


在Dalvik新进程创建的最关键一步是使用linux的Fork机制从zygote母体Fork出一个新的进程来。到了这里有如下值得关注的地方:


由于是linux的Fork机制,新进程复制Zygote的可共享虚拟地址空间的页表页目录。而不可共享区域由linux自身的COW机制在写时机创建
Zygote已经进行大量的初始化,加载了大量的常用类库,大量的二进制链接库,都被新进程继承下来。
新进程如果有什么异常状况,可以轻易被kernel杀掉,只要systemserver跟zygote没有问题,系统仍然可以健康的运行。
在新进程运行应用代码之前构建Android进程安全框架。除了传统的通过用户ID、组ID将进程文件访问限制在自己局部区域,通过Capabilities能力位更加细分的控制对内核访问以外。 


Zygote Fork新进程的实现如下:
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
    pid_t pid;


    //新进程的UID和GID,这是在由PackagemangeService传送过的。
uid_t uid = (uid_t) args[0];
    ... 
//调用linux系统调用Fork
    pid = fork();
    //完成Fork动作,新老进程都从这里返回
if (pid == 0) {
//进程的返回的pid为零
/*至此新进程的实体被创建完毕,但是这离Android进程还有几步要走。首先这是由Zygote Fork出的进程,他具有与Zygote相同的权限,这是不被允许的,不然Android上的恶意病毒就可以为所欲为了。而新进程到了这里还没有加载APK的.so和dex,所以新进程在这里自废武功限制自己以后的所为,等到加载了恶意的APK也不怕伤及筋骨了。*/
       /*新版Android的安全性更进一步,支持基于Selinux的面向企业应用的更高级别的安全性,但是本节摘自较早笔记,其版本没有涉及到Selinux的适配。由于时间关系,针对SEAndroid/SElinux的分析不在本书设计的范围之内。*/
#ifdef HAVE_ANDROID_OS
        …
        /* keep caps across UID change, unless we're staying root */
        if (uid != 0) {
            err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
         …
#endif /* HAVE_ANDROID_OS */
       
        //重置用户组
        err = setgroupsIntarray(gids);
        …
       //设置资源限制
        err = setrlimitsFromArray(rlimits);
        …
        //重置GID
        err = setgid(gid);
        …
        //重置UID
        err = setuid(uid);
        …
        //Capabilities位的设置
        err = setCapabilities(permittedCapabilities, effectiveCapabilities);
        …
        //设置DVM控制结构的线程号
        Thread* thread = dvmThreadSelf();
        thread->systemTid = dvmGetSysThreadId();
        …
    } else if (pid > 0) {
        /* the parent process */
    }
    return pid;
}


再往后,父子进程都退到zygote中,但是父进程继续等待下一个新的DVM进程创建申请,子进程在清空原有的JAVA栈之后开始了新生。

你可能感兴趣的:(java,虚拟机,线程,android,dalvik)