Zygote进程简介

本文基于Android_9.0、kernel_3.18源码

zygote启动流程

Android手机进程

打开控制台,使用adb shell,然后执行ps -A命令;便可看到Android系统中运行的进程。PID是进程号,PPID是父进程号。PID越小启动越早。

Android手机进程

主要进程之间的关系

通过梳理我们可以得到以下的关系图:
进程关系

init进程

打开android手机后,会先启动bootloader引导程序,当kernel完成系统设置后,它会拉起init进程。init进程主要进行文件夹创建挂载、init.rc文件解析等操作。

system/core/init/init.cpp
system/core/rootdir/init.rc
xref/system/core/rootdir/init.zygote32.rc

1、init.cpp->main()

int main(int argc, char** argv) {
    ...
    if (is_first_stage) {
        ...
        // 创建文件夹并挂载
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        ...
    }
    ...
    
    property_init(); // 初始化property
    
    process_kernel_dt(); // 加载dt的数据
    process_kernel_cmdline(); // 加载cmd的数据
    ...

    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sm = ServiceList::GetInstance();

    // 加载启动脚本
    LoadBootScripts(am, sm);

    // 添加其他任务
    am.QueueEventTrigger("early-init");
    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    ...

    // 循环执行任务
    while (true) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;
        ...

        // 执行任务
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || Service::is_exec_service_running())) {
            if (!shutting_down) {
                auto next_process_restart_time = RestartProcesses();

                // 如果有进程需要重启,设置超时时间
                if (next_process_restart_time) {
                    epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(*next_process_restart_time - boot_clock::now()).count();
                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
                }
            }

            // 如果还有任务需要执行,设置超时为0
            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
        }

        epoll_event ev;
        // epoll阻塞,等待唤醒、超时
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
        ...
    }

    return 0;
}

查看main函数,它主要做了如下操作:

<1>创建文件夹并挂载
<2>初始化属性
<3>解析init.rc文件
<4>启动任务(Action)

2、init.rc

...
// 引入zygote.rc文件
import /init.${ro.zygote}.rc
...

# Mount filesystems and start core system services.
on late-init
    ...
    # Now we can start zygote for devices with file based encryption
    trigger zygote-start
    ...

...

在init.rc文件中,引入了init.zygote32.rc,并设置了zygote的启动时机。
属性ro.zygote的值可能有:zygote32、zygote64、zygote32_64、zygote64_32。

3、init.zygote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

zygote服务最终触发了app_process可执行文件,并携带参数 –zygote–start-system-server
搜索源码,可以看到app_process目录下的文件,app_process可执行文件就是由app_main.cpp编译出来的。

app_process文件夹

zygote进程-native

frameworks/base/cmds/app_process/app_main.cpp

1、app_main.cpp->main()

#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif

// service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
int main(int argc, char* const argv[]){
    ...
    // 实例化AppRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    // 解析参数,解析完毕后的值分别为
    // zygote = true
    // startSystemServer = true
    // niceName = ZYGOTE_NICE_NAME (zygote)
    // application = false
    // className = null
    ++i;
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
       ...
    } else {
        ...
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
        ...

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // 将剩余参数传递给ZygoteInit的main方法
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    // 修改进程名称
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        ...
    } else {
        ...
    }
}

void AndroidRuntime::setArgv0(const char* argv0, bool setProcName) {
    if (setProcName) {
        int len = strlen(argv0);
        if (len < 15) {
            pthread_setname_np(pthread_self(), argv0);
        } else {
            pthread_setname_np(pthread_self(), argv0 + len - 15);
        }
    }
    memset(mArgBlockStart, 0, mArgBlockLength);
    strlcpy(mArgBlockStart, argv0, mArgBlockLength);
}

首先, main方法会循环遍历传入的参数;
然后, 通过setArgv0修改当前进程的名字为zygote;
最后, 启动com.android.internal.os.ZygoteInit的main函数,将参数传递过去。

2、AndroidRuntime.cpp->start()

class AppRuntime : public AndroidRuntime{
    ...
}

// 开启Android虚拟机, 并调用className的main方法
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
    ...

    // 检查rootDir
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    // 启动Android虚拟机
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 注册andorid方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    // 设置类名、参数
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    // 找到class
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ...
    } else {
        // 找到main方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ...
        } else {
            // 调用方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            ...
        }
    }
    free(slashClassName);
    ...
}

AppRuntime继承自AndroidRuntime,通过调用runtime->start()会调用到AndroidRuntime的方法:
首先, 通过startVm(&mJavaVM, &env, zygote)开启Android虚拟机;
然后, 通过startReg(env)注册Android方法;
最后, 通过className找到jclass和对应的main方法,调用ZygoteInit的main。

3、startReg()

struct RegJNIRec {
    int (*mProc)(JNIEnv*);
    const char* mName;
};

static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    REG_JNI(register_android_os_SystemClock),
    ...
}

int AndroidRuntime::startReg(JNIEnv* env){
    ...
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {}
    ...
    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env){
    for (size_t i = 0; i < count; i++) {
        // 执行mProc方法
        if (array[i].mProc(env) < 0) {
            ...
            return -1;
        }
    }
    return 0;
}

在startReg中会通过register_jni_procs遍历执行gRegJNI中注册的方法;其中gRegJNI是一个RegJNIRec的数组。

zygote进程-java层

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

1、ZygoteInit.java->main()

public static void main(String argv[]) {
    // 持有LocalServerSocket
    ZygoteServer zygoteServer = new ZygoteServer();
    ...
    final Runnable caller;
    try {
        ...
        // 解析参数,解析完毕后的值分别为
        // startSystemServer = true;
        // socketName = zygote;
        // enableLazyPreload = false;
        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;
        ...
        // 注册socket服务
        zygoteServer.registerServerSocketFromEnv(socketName);
        if (!enableLazyPreload) {
            ...
            // 预加载
            preload(bootTimingsTraceLog);
            ...
        } else {}
        // 进行一次gc
        gcAndFinalize();
        Zygote.nativeSecurityInit();
        Zygote.nativeUnmountStorageOnInit();
        ZygoteHooks.stopZygoteNoThreadCreation();
        // 启动system_server
        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
            // child (system_server) process.
            if (r != null) {
                r.run();
                return;
            }
        }
        // 在zygote进程中轮询,不会在子进程中执行,因为上边已经return了
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        ...
    } finally {
        // 轮询终止,关闭socket
        zygoteServer.closeServerSocket();
    }
    // 直接结束代码
    if (caller != null) {
        caller.run();
    }
}

在main中,做了如下操作:

<1>解析传入的参数startSystemServer = true、enableLazyPreload = false
<2>通过registerServerSocketFromEnv()注册socket服务
<3>preload()预加载
<4>gcAndFinalize()执行gc
<5>fork子进程启动system_server
<6>zygoteServer.runSelectLoop()开启轮询,等待client消息

2、preload()

static void preload(TimingsTraceLog bootTimingsTraceLog) {
    Log.d(TAG, "begin preload");
    bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
    beginIcuCachePinning();
    bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
    bootTimingsTraceLog.traceBegin("PreloadClasses");
    
    // 加载class
    preloadClasses();
    bootTimingsTraceLog.traceEnd(); // PreloadClasses
    bootTimingsTraceLog.traceBegin("PreloadResources");

    // 加载资源
    preloadResources();
    bootTimingsTraceLog.traceEnd(); // PreloadResources
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
    nativePreloadAppProcessHALs();
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");

    // 加载OpenGL
    preloadOpenGL();
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    preloadSharedLibraries();
    preloadTextResources();
    // Ask the WebViewFactory to do any initialization that must run in the zygote process,
    // for memory sharing purposes.
    WebViewFactory.prepareWebViewInZygote();
    endIcuCachePinning();
    warmUpJcaProviders();
    Log.d(TAG, "end preload");
    sPreloadComplete = true;
}

preload会提前加载Android系统类和系统资源(系统提供的布局等),简单分析一下preloadClasses

3、preloadClasses()

private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

private static void preloadClasses() {
    InputStream is;
    try {
        is = new FileInputStream(PRELOADED_CLASSES);
    } catch () {}
    ...
    try {
        BufferedReader br = new BufferedReader(new InputStreamReader(is), 256);
        String line;
        while ((line = br.readLine()) != null) {
            ...
            try {
                // 加载class
                Class.forName(line, true, null);
            } catch () {}
        }
        ...
    } catch (IOException e) {} finally {}
}

其是这个方法就是读取PRELOADED_CLASSES路径下的文件,然后找到配置的类名,通过Class.forName()加载class。

preloaded-classes

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值