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 语法编写的脚本。

解析 Service Section 流程

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

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

1
2
3
4
5
6
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

由于 zygote 属于 Service,所以举例解析 Service 的流程图,解析 Action 的流程类似

进入 Java 世界

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

init.rc

1
2
3
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

1
2
3
4
5
6
7
8
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main // 指定服务的类名。 同一个类名中的所有服务可以一起启动或停止。 如果未通过 class 选项指定服务,则服务在类“default”中
priority -20 // 调度服务进程的优先级。 该值必须在 [-20,19] 的范围内。默认优先级为 0
user root
group root readproc
socket zygote stream 660 root system // 创建一个名为 /dev/socket/nameUNIXsocket,并将其 fd 传递给已启动的进程
...
writepid /dev/cpuset/foreground/tasks // 当 forks 时,将 child 进程的 pid 写入给定的文件

所以这里会执行在解析配置阶段构造的对应 zygote service 配置的 Service 对象的 Start() 方法。

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 开始运行.

主流程

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, 说明在子进程中. 执行 runSelectLoop 返回的 Runnable
if (caller != null) {
caller.run();
}
}

registerServerSocket

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
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
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);
}
}
}

forkSystemServer

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
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
// ...
/* 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,30023003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
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 */
// 通过 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 的 Socket, 所以关掉
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}

runSelectLoop

在启动 SystemServer 之后, 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) {
}
}
}
}

参考