Android Zygote进程启动及工作简介

Linux内核启动
  1. 电源按下,当CPU最后完成复位后,CPU执行第一条指令,从一个固定地址中执行引导程序(BootLoader).
  2. BootLoader作用是装在内核程序进行初始化并运行.
  3. 内核完成设置,启动init进程.
init进程主要工作
  1. 初始化和启动属性服务
  2. 启动Zygote进程
  3. 挂载一些系统文件
init进程的启动
  1. 内核启动init进程会首先寻找init.rc,然后启动init进程.init进程入口函数main()
  2. init.rc由Android初始化语言编写的脚本(Android Init Language),init进程解析该脚本就能启动Zygote进程
Zygote概述
  1. Dalvik虚拟机与ART,应用程序进程,SystemServer进程都是由Zygote进程来创建.
  2. Zygote进程启动时会创建Dalvik虚拟机或者ART进程.
  3. Zygote通过fork(复制进程)的形式来创建APP进程,SystemServer进程.所以SystemServer进程或者APP进程中可以获取Dalvik虚拟机或者ART进程.
  4. Zygote进程起初名为app_process,这个名称是在Android.mk中定义的,Linux系统下的pctrl系统会调用app_process,将其进程名称换为zygote.
Zygote进程启动
  • Zygote进程对应的源文件为app_main.cpp
    1. Zygote进程是通过fork自身来创建子进程,所以像SystemServer进程和App进程都能走到main()中来
// app_main.cpp
int main(int argc, char* const argv[])
{
    // 创建runtime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ...
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            // 当前运行是否在zygote进程中
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            // 当前运行是否在SystemServer进程中
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            // 当前运行是否在APP进程中
            application = true;
        } 
        ...
    }

    ...
    if (zygote) {
        // 假如是运行在zygote进程中,下面看AndroidRuntime.cpp中的start().
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}
// AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    // 启动java虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 为java虚拟机注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    ...
    // 找到 ZygoteInit 的 main 方法 
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
    // 通过JNI调用ZygoteInit的main()方法
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    ...
}
  • Native层调用ZygoteInit.main()后,逻辑就到java层了.
// ZygoteInit.java
public static void main(String argv[]) {
    try {
         boolean startSystemServer = false; // 是否启动 SystemServer
         String socketName = "zygote";      // 创建的socket服务端的名称
         String abiList = null;             // 支持的so库的类型
         for (int i = 1; i < argv.length; i++) {
             if ("start-system-server".equals(argv[i])) {
                 startSystemServer = true;
             } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                 abiList = argv[i].substring(ABI_LIST_ARG.length());
             } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
             } else {
                 throw new RuntimeException("Unknown command line argument: " + argv[i]);
             }
         }
        ...
        // 创建一个Server端的Socket,socketName=zygote.
        registerZygoteSocket(socketName);
        // 预加载类和资源 
        preload();
        if (startSystemServer) {
            // 启动SystemServer进程
            startSystemServer(abiList, socketName);
        }
        // 等待AMS请求
        runSelectLoop(abiList);
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        caller.run();
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}
  • 创建一个Socket服务端
public class ZygoteInit {
    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            // 拼接Socket的名称
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                // 得到Socket的环境变量
                String env = System.getenv(fullSocketName);
                // 将Socket环境变量值转换为文件描述符参数
                fileDesc = Integer.parseInt(env);
            } 
            ...
            try {
                // 创建文件描述符
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                // 创建服务器端Socket
                sServerSocket = new LocalServerSocket(fd);
            } 
        }
    }
}
  • SystemServer进程创建好了之后,AMS服务也就准备好了, 然后服务端Socket就可以监听AMS发送过来的创建APP进程的消息了.
public class ZygoteInit {
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        // 获取服务端Socket的文件描述符,然后存入fds中
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
        // 循环等待AMS请求Zygote进程创建新的APP进程
        while (true) {
            // 将fds中的文件描述符存入pollFds中
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                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) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    // 无效消息,跳过
                    continue;
                }
                if (i == 0) {  // Socket服务端收到了一个链接请求,SystemServer进程已经与Zygote进程建立了链接.
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    // 将对象存入列表
                    peers.add(newPeer);
                    // 将文件描述符存入列表, 
                    // 从这里可以知道下一次循环i将等于1
                    fds.add(newPeer.getFileDesciptor());
                } else { // i=1, Socket服务端收到了数据.
                    // 这里就得到ZygoteConnection中看了
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        // 创建成功就删除刚刚的ZygoteConnection对象和对应得文件描述符.
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
    // 创建一个ZygoteConnection.
    private static ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            // sServerSocket.accept() 等待链接获取Socket实例
            return new ZygoteConnection(sServerSocket.accept(), abiList);
        } catch (IOException ex) {
            throw new RuntimeException(
                    "IOException during accept()", ex);
        }
    }
}
  • 看看ZygoteConnection.runOnce()
class ZygoteConnection {
    ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
        mSocket = socket;
        this.abiList = abiList;
        mSocketOutStream = new DataOutputStream(socket.getOutputStream());
        mSocketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()), 256);
        mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
        try {
            peer = mSocket.getPeerCredentials();
        } catch (IOException ex) {
            Log.e(TAG, "Cannot read peer credentials", ex);
            throw ex;
        }
    }
    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ...
        // 创建子进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
       if (pid == 0) {
           ...
           // 处理刚fork出的子进程 
           // 新旧版本源码这里的区别太大了, 暂时不分析了. 
           handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
           return true;
       } else {
           ...
           return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
       }    
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值