This page looks best with JavaScript enabled

Android init 进程的启动过程

 ·  ☕ 8 min read

init 进程是 Android 系统中用户空间的第一个进程,进程号为 1。作为第一个进程,它被赋予了很多重要的职责,比如创建 Zygote 进程和属性服务等。

init 进程由多个源文件共同组成,这些文件位于源码目录 system/core/init 中。

Android 系统启动的前几步

  1. 当电源接通时。引导芯片代码从预定义的地方(硬编码在 ROM)开始执行。加载引导程序 BootLoader 到 (内存)RAM 中,然后执行。

  2. BootLoader 是在 Android 系统开始运行前的一个小程序(它不是 Android 的一部分)。BootLoader 是制造商放置锁定和限制的地方。BootLoader 分两个阶段执行。 在第一阶段,它检测外部 RAM 并加载程序。在第二阶段,为内核启动做准备,引导加载程序设置网络,内存等

  3. Android 内核的启动方式与 Linux 内核类似。随着内核的启动,开始设置缓存,受保护的内存,调度和加载驱动程序。当内核完成系统设置时,它会在系统文件中查找 init 文件。

  4. init 进程启动

  • 创建和挂载启动所需的文件目录
  • 初始化和启动属性服务
  • 解析 init.rc 脚本,并启动 Zygote 进程

init 进程的入口

在 Android 内核加载完成后,它会执行 init 进程的入口函数 mainmain 函数中会解析 init.rc 配置文件到 Action Service 对象中,然后执行 Actions 中的命令。

init.rc 是按照 Android Init Language 语法编写的脚本。

在 init 进程在执行 main 方法时,会解析执行 /init.rc 脚本,init.rc 脚本中会 import 与 zygote 相关的 init.${ro.zygote}.rc 脚本:

ro.zygote 是一个编译期指定的属性值,可以为 zygote32、zygote64、zygote32_64、zygote64_32

init.rc 内容如下:

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

init.zygote64.rc 内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main   //指定服务的类名。 同一个类名中的所有服务可以一起启动或停止。 如果未通过 class 选项指定服务,则服务在类“default”中
    priority -20 //调度服务进程的优先级。 该值必须在 [-20,19] 的范围内。默认优先级为 0
    user root    //所属用户
    socket zygote stream 660 root system  //创建一个名为 /dev/socket/name 的 UNIX 域 socket,并将其 fd 传递给已启动的进程
    socket usap_pool_primary stream 660 root system
    onrestart write /sys/power/state on   //onrestart 表示在重启时执行的动作
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks //将进程id写入文件

进入 Java 世界

待配置文件解析完成之后,就会开始依次执行 Actions 里的命令,在 init.rc 中能看到有如下配置:

init.rc

on nonencrypted
    class_start main // 执行 class_start 命令,参数为 main
    class_start late_start

表示当 nonencrypted 事件发生时,就执行下面定义的命令 class_start main 等。

system/core/init/builtins.cpp 中每个命令对应的解析函数关系

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    static const Map builtin_functions = {
        ...
        {"class_reset",             {1,     1,    do_class_reset}},
        {"class_restart",           {1,     1,    do_class_restart}},
        {"class_start",             {1,     1,    do_class_start}},
        ...
        {"write",                   {2,     2,    do_write}},
    };
    return builtin_functions;
}

所以 class_start main 会执行 do_class_start 方法,并传递参数 main:

1
2
3
4
5
static int do_class_start(const std::vector<std::string>& args) {
    ServiceManager::GetInstance().ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
    // 循环执行 class name 匹配 args[1](这里是main) 的 Service 的 StartIfNotDisabled
    return 0;
}
1
2
3
4
5
6
7
8
bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {
        return Start();
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
}

init.zygote64.rc 中配置的 zygote 服务的 class name 恰恰就是 main, 所以这里会执行在 zygote 配置的 Service 对象的 Start() 方法。

@startuml
Service -> Service: Start
Service -> Service: fork
note right: fork 进程,接下来的操作在子进程中
Service -> Service: ExpandArgsAndExecve
note right: 调用 execve 执行 zygote service 的程序\n system/bin/app_process64\n其对应源码为app_main.cpp
Service -> app_main.cpp: main
app_main.cpp -> AndroidRuntime: start("com.android.internal.os.ZygoteInit")
AndroidRuntime -> AndroidRuntime: startVM
note right: 启动 JVM
AndroidRuntime -> JNIEnv: CallStaticVoidMethod
note right: 调用 ZygoteInit 类的静态方法: main
JNIEnv -> ZygoteInit: main
@enduml

ServiceStart() 会最终执行 zygote service 配置中的参数 system/bin/app_process64 程序, 其对应源码为app_main.cpp.

frameworks/base/cmds/app_process/app_main.cpp

app_main.cpp 的 main 方法接收的参数就是在 init.zygote64.rc 中配置的 --zygote --start-system-server

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int main(int argc, char* const argv[]) {
    //...
    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;
        }
    }
    //...
    if (zygote) {
        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.");
    }
}

app_main.cppmain 方法中会调用 AndroidRuntimestart 方法, 进而 startVM 启动 JVM, 然后通过 JNIEnv 调用 ZygoteInit Java 类的静态方法 main. 至此, 就从 cpp 世界进入了 java 世界.

frameworks/base/core/jni/AndroidRuntime.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
    // className: com.android.internal.os.ZygoteInit
    //...
    // 启动 JVM
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    //...

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     * 创建一个 strArray 存放相关参数
     */
    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);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    // com.android.internal.os.ZygoteInit 转变为 com/android/internal/os/ZygoteInit
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        // 获取 ZygoteInit 类的 static void main 方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
            // 调用 main 方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
}

Zygote 进程启动

进入 Java 世界之后, 程序从 ZygoteInit 类的 main 开始运行.

主流程

@startuml
ZygoteInit -> ZygoteInit: main
ZygoteInit -> ZygoteServer: registerServerSocket
ZygoteInit -> ZygoteInit: preload
group 启动 SystemServer 进程 
    ZygoteInit -> Zygote: forkSystemServer
    Zygote -> Zygote: nativeForkSystemServer
    Zygote --> ZygoteInit: pid
    ZygoteInit -> ZygoteServer: closeServerSocket
    ZygoteInit -> ZygoteInit: handleSystemServerProcess
end
ZygoteInit -> ZygoteServer: runSelectLoop
ZygoteInit -> ZygoteServer: closeServerSocket
@enduml

ZygoteInit.java#main

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    //...
    final Runnable caller;
    try {
        //...
        // 创建一个 LocalServerSocket, 用来接收其他服务的请求. socketName 为 zygote
        zygoteServer.registerServerSocket(socketName);
        //...
        if (startSystemServer) {
            // 通过 fork 一个子进程来启动 System Server
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            // {@code r == null } 说明还是运行在父(zygote)进程
            // {@code r != null } 说明运行在子进程(system_server)
            if (r != null) {
                r.run();
                // 这里的 return 是让子进程(system_server)不执行下面的代码, zygote 进程中代码还是继续向下运行
                return;
            }
        }

        // 运行 Zygote 进程的循环来等待 AMS 的请求
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        throw ex;
    } finally {
        zygoteServer.closeServerSocket();
    }

    // 如果 caller != null, 说明在 zygote 进程中. 执行 runSelectLoop 返回的 Runnable
    if (caller != null) {
        caller.run();
    }
}

registerServerSocket

创建 Zygote 接受事件的 Server Socket

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
void registerServerSocket(String socketName) {
    if (mServerSocket == null) {
        int fileDesc;
        // 拼接 scoket name 为: ANDROID_SOCKET_zygote
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException(fullSocketName + " unset or invalid", ex);
        }
        try {
            // 创建文件描述符
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            // 创建 LocalServerSocket
            mServerSocket = new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
        }
    }
}

启动 SystemServer

通过调用 forSystemServer 启动 SystemServer 进程。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
    // ...
    // 一些参数设置
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--nice-name=system_server",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

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

        // fork 当前进程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    if (pid == 0) {
        // fork 成功之后, 在子进程中运行下面的代码
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        // 因为 SystemServer 用不到 Zygote 的 Server Socket, 所以关掉
        zygoteServer.closeServerSocket();
        // 在 SystemServer 进程做一些工作
        return handleSystemServerProcess(parsedArgs);
    }
    // 父进程方法调用结束
    return null;
}

handleSystemServerProcess

SystemServer 进程 fork 成功之后,在其进程做一些工作。比如:加载一些系统类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    //...
    if (parsedArgs.mInvokeWith != null) {
        //...
    } else {
        // 创建 PathClassLoader 作为系统 ClassLoader
        createSystemServerClassLoader();
        ClassLoader cl = sCachedSystemServerClassLoader;
        if (cl != null) {
            // 注入到 ContextClassLoader 中
            Thread.currentThread().setContextClassLoader(cl);
        }
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mDisabledCompatChanges,
                parsedArgs.mRemainingArgs, cl);
    }
}

zygoteInit

每个从 zygote 进程 fork 而来的进程都会执行 zygoteInit 方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
    // 将System.out和System.err重定向到Android日志。
    RuntimeInit.redirectLogStreams();
    // 做一些公共的操作,比如:设置系统的 User-Agent
    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit();
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
            classLoader);
}

applicationInit

1
2
3
4
5
6
7
8
9
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
    final Arguments args = new Arguments(argv);
    // 找到参数中 startClass 的 static main 方法
    // 这里 startClass 是: com.android.server.SystemServer
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    Class<?> cl;
    // 获取目标类
    cl = Class.forName(className, true, classLoader);
    Method m;
    // 获取目标类的 main 方法
    m = cl.getMethod("main", new Class[] { String[].class });
    // MethodAndArgsCaller 是一个 Runnable, run 时会执行方法 m, 并传递参数 argv
    return new MethodAndArgsCaller(m, argv);
}

启动 SystemServer 的过程可以概述为:

  1. fork zygote 进程
  2. 关闭 zygote 的 server socket
  3. 在 fork 的进程中加载 com.android.server.SystemServer 类,并调用 SystemServer 类的 main 方法

runSelectLoop

在 zygote 进程, ZygoteServer 会继续执行 runSelectLoop 方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    // 获取通过 registerServerSokcet 创建的 socket 的 FileDescriptor, 添加到 fd 列表 fds 中
    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);
    // 无限循环
    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;
            // 设置 StructPollfd 等待的事件为 POLLIN
            // POLLIN: 表示有数据可读
        }
        try {
            // Linux poll 调用: 等待一组文件描述符中的一个准备好执行 I/O, -1 表示一直等待
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        // 从 pollFds 末尾开始遍历
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                // revents: 实际发生的事件
                // 如果实际发生的事件不为 POLLIN, 则跳过后面步骤
                continue;
            }
            // i == 0: 表示是 mServerSocket 的 FileDescriptor 发生了 POLLIN 事件. 因为 mServerSocket 的 FileDescriptor 是在无限循环之前添加到 fds 中的, 其 index 一定为 0
            if (i == 0) {
                // 从 mServerSocket accept 一个客户端的 socket 连接, 封装为 ZygoteConnection
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                // 将客户端的 socket FileDescriptor 添加到 fds 中
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 能走到这里的 fd 都是客户端的 socket 的 fd
                try {
                    ZygoteConnection connection = peers.get(i);
                    final Runnable command = connection.processOneCommand(this);
                    // processOneCommand 执行成功,最终返回一个 Runnable:
                    // ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */);
                    if (mIsForkChild) {
                        // mIsForkChild 在 processOneCommand 当 fork 成功之后会设置
                        // We're in the child. We should always have a command to run at this
                        // stage if processOneCommand hasn't called "exec".
                        if (command == null) {
                            throw new IllegalStateException("command == null");
                        }
                        return command;
                        //return 到 ZygoteInit#main 最下面的 caller
                    } else {
                        // fork 失败或者执行 processOneCommand 期间其他参数错误
                        // We're in the server - we should never have any commands to run.
                        if (command != null) {
                            throw new IllegalStateException("command != null");
                        }
                        // We don't know whether the remote side of the socket was closed or
                        // not until we attempt to read from it from processOneCommand. This shows up as
                        // a regular POLLIN event in our regular processing loop.
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                } catch (Exception e) {
            }
        }
    }
}

看完整体过程,init 进程的启动过程可以概要为:

  1. 解析 init.rc 脚本,执行 app_process 程序
  2. app_process 程序运行后会创建 Java VM
  3. Java VM 创建成功之后,会执行 Java 类 ZygoteInit 的 main 方法从而创建 ZygoteServerSocket、启动 SystemService

参考

Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer