Zygote进程启动过程

上篇文章《浅析Android系统启动过程》简要讲解了Android系统整体启动过程,今天我们看一下其中一个重要的过程:Zygote进程是如何启动的。

文中源码基于Android 8.0

概览

Zygote进程是通过init进程启动起来的,我们直接看Zygote进程的入口函数,位于ZygoteInit类中的main方法:

public class ZygoteInit {
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        //创建Socket
        zygoteServer.registerServerSocket(socketName);
        
        //预加载类和资源
        preload(bootTimingsTraceLog);
        
        //启动SystemServer进程
        startSystemServer(abiList, socketName, zygoteServer);
        
        //进入循环等待请求
        zygoteServer.runSelectLoop(abiList);

由上面代码可以看出Zygote进程主要做了4件事:

  1. 创建一个Socket用于跨进程通信
  2. 预加载类和资源
  3. 启动SystemServer进程
  4. 进入循环等待AMS请求创建新的应用程序进程

我们继续跟进看看各个方法具体做了什么,

registerServerSocket

创建socket用于跨进程通信

void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            //拼接socket名称
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                //获取socket环境变量
                String env = System.getenv(fullSocketName);
                //将socket环境变量转换为fd文件描述符的参数
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                //创建fd文件描述符
                FileDescriptor fd = new FileDescriptor();
                //设置fd参数
                fd.setInt$(fileDesc);
                //传入fd创建Socket
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

preload

预加载各种类及资源

static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
        
        //预加载/system/etc/preloaded-classes目录下常用的类
        preloadClasses();
        
        //预加载drawables、color、freeform_multi_window_drawables等常用资源
        preloadResources();
        
        //预加载OpenGL
        preloadOpenGL();
        
        //预加载android、compiler_rt、jnigraphics库
        preloadSharedLibraries();
        
        //预加载字体资源
        preloadTextResources();
        
    }

startSystemServer

启动SystemServer进程

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_PTRACE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG,
            OsConstants.CAP_WAKE_ALARM
        );
        /* Containers run without this capability, so avoid setting it in that case */
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        }
        /* Hardcoded command line to start the system server */
        
        
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };//---1---
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);//---2---
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            handleSystemServerProcess(parsedArgs);//---3---
        }

        return true;
    }

注释1处创建args数组,用来保存用于启动SystemServer进程的启动参数。注释2处调用Zygote.forkSystemServer方法,通过fork当前进程来创建SystemServer进程,如果进程的pid值为0,则表示当前运行在新创建的进程中,就会执行注释3处的handleSystemServerProcess来处理SystemServer进程。关于SystemServer进程的启动放在之后的文章讲解。

runSelectLoop

死循环等待AMS请求

void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        //---1---
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);

        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {//---2---
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {//---3---
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);//---4---
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce(this);//---5---
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

注释1处获取之前创建的socketfd添加到fds中,然后进入无限循环来等待AMS请求Zygote进程创建新的应用程序进程。注释2处遍历fds存储的信息放到pollFds中。注释3处对pollFds进行遍历,如果i=0说明pollFds中没有内容,此时会通过注释4处acceptCommandPeer方法创建一个ZygoteConnection,然后获取ZygoteConnectionfd并加入到fds中,以便接收下次AMS的请求。而当i!=0时,会执行注释5处的peers.get(i).runOnce(this),这个方法用来处理AMS发送过来的请求,处理完后,将ZygoteConnectionpeers中移除,将fdfds中移除,并进入下次循环。

学习更多知识,请关注我的个人博客:droidYu

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值