相关文章
Android系统启动流程(1) —— 解析init进程启动过程
Zygote 进程启动过程
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。由于zygote进程在Android系统中有着如此重要的地位,本文将详细分析它的启动过程。
1. Zygote简介
在Android系统中,DVM(Dalvik虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由zygote进程来创建的,我们也将它称为孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于zygote进程在启动时会创建DVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。
关于init启动zygote我们在上一篇文章已经提到了,这里就不赘述了,这篇文章主要分析Android8.1系统的zygote进程的启动流程。
2. Zygote启动脚本
在init.rc文件中采用了Import类型语句来引入Zygote启动脚本,这些启动脚本都是由Android初始化语言(Android Init Language)来编写的,引入Zygote脚本代码如下:
system/core/init/init.cpp
import /init.${ro.zygote}.rc
在init.rc中通过属性ro.zygote的值来引入不同的zygote启动脚本的。从Android5.0开始,Android开始支持64位程序,Zygote也就有了32位和64位的区别了,所以在这里用 ro.zygote 属性来控制使用不同的 Zygote 启动脚本,从而也就启动了不同版本zygote进程, ro.zygote 属性的取值有以下4种:
- init.zygote32.rc
- init.zygote32_64.rc
- init.zygote64.rc
- init.zygote64_32.rc
1. init.zygote32.rc
表示支持纯 32 位程序, 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
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
根据 Service类型语句的格式,可以得知 Zygote 进程名称为zygote ,执行程序为 app _process, class name为main ,如果 audioserver cameraserver、 media、netd、wificond 进程终止了,就需要进行 restart (重启 )。
2. init.zygote32_64.rc
表示既支持 32 位程序也支持64位程序, init.zygote32_64.rc 文件内容如下所示:
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc
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
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
user root
group root readproc
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
3. init.zygote64.rc
表示支持纯 64 位程序, init.zygote64.rc 文件内容如下所示:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
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
根据 Service类型语句的格式,可以得知 Zygote 进程名称为zygote ,执行程序为 app _process64, class name为main ,如果 audioserver cameraserver、 media、netd、wificond 进程终止了,就需要进行 restart (重启 )。
4. init.zygote64_32.rc
表示既支持 32 位程序也支持64位程序, init.zygote64_32.rc 文件内容如下所示:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc
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
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
脚本中有两个Service类型语句,说明会启动两个zygote 进程, 第一个名称为 zygote,执行程序为 app_process64 ,作为主模式 ;第二个名称为 zygote_secondary,执行程序为 app _process ,作为辅模式。
3. Zygote 进程启动过程介绍
在init启动zygote进程是主要是调用App_mian.cpp的main函数中的AppRuntime的start方法来启动zygote进程的,那我们就从App_main.cpp的main函数开始分析,代码如下:
frameworks/base/cmds/app_process/App_main.cpp
int main(int argc, char* const argv[])
{
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { // ... 1
// 如果当前运行在zygote进程中,则将zygote设置为true
zygote = true; // ... 2
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) { // ... 3
// 如果当前运行在SystemServer进程中,则将startSystemServer设置为true
startSystemServer = true; // ... 4
} 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 (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
// 如果运行在zygote进程中
if (zygote) { // ... 5
runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // ... 6
} 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.");
}
}
由于zygote进程都是通过fock自身来创建子进程的,所以zygote进程以及它的子进程都可以进入App_main.cpp的main函数,因此main函数中为了区分当前运行在哪个进程中,会在注释1处判断参数 arg中是否包含了“--zygote”,如果包含了则说明main函数是运行在 zygote 进程中的并在注释2处将 zygote设置为ture,同理在注释3处判断参数arg中是否包含了“--start-system-server”,如果包含了则说明 main 函数是运行在SystemServer进程中的并在注释4处将 startSystemServer设置为true。
在注释5处,如果zygote为true,就说明当前运行在zygote进程中,就会调用注释6处的runtime的start函数,runtime指的就是AppRuntime,AppRuntime声明也在App_main.cpp中,它继承AndroidRuntime,但是AppRuntime并没有重写start函数,也就是说我们调用start函数其实调用的就是AndroidRuntime的start函数,如下所示:
frameworks/base/cmds/app_process/App_main.cpp
class AppRuntime : public AndroidRuntime
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// 启动java虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) { // ... 1
return;
}
onVmCreated(env);
/*
* Register android functions.
* 为java虚拟机注册JNI方法
*/
if (startReg(env) < 0) { // ... 2
ALOGE("Unable to register all android natives\n");
return;
}
...
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
// 从App_main的main函数得知,className为com.android.internal.os.ZygoteInit
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.
*/
// 将className的"."替换为"/"
char* slashClassName = toSlashClassName(className != NULL ? className : ""); // .. 4
// 找到ZygoteInit
jclass startClass = env->FindClass(slashClassName); // ... 5
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到ZygoteInit的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); // ... 6
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray); // ... 7
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer()
...
String socketName = "zygote";
...
try {
...
// 创建一个Server端的Socket,socketName的值为"zygote"
zygoteServer.registerServerSocket(socketName); // ... 1
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 预加载类和资源
preload(bootTimingsTraceLog); // ... 2
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
if (startSystemServer) {
// 启动SystemServer进程
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;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
// 等待AMS请求
caller = zygoteServer.runSelectLoop(abiList); // 4
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
在注释1处通过registerServerSocket 方法来创建 Server 端的 Socket ,这个name 为“zygote”的 Socket 用于等待 ActivityManagerService 请求 Zygote 来创建新的应用程序进程,后续会出AMS相关的文章解析AMS,这里就先不做介绍了。在注释2处预加载类和资源。在注释3处启动 SystemServer进程,这样系统的服务也会由 SystemServer进程启动起来。在注释4处调用 zygoteServer.runSelectLoop 方法来等待 AMS 请求创建新的应用程序进程。由此得知, Zygotelnit的main方法主要做了4件事:
1 . registerZygoteSocket
首先我们来查看 ZygoteServer的registerZygoteSocket 方法做了什么,代码如下所示:
frameworks/base/core/java/com/android/internal/os/ZygoteServe.java
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
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环境变量的值转化为文件描述符的参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
// 创建文件描述符
FileDescriptor fd = new FileDescriptor();
// 设置文件描述符的参数
fd.setInt$(fileDesc);
// 创建服务器端Socket
mServerSocket = new LocalServerSocket(fd); // ... 1
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
2. 启动SystemServer进程
接下来查看 forkSystemServer方法, 代码如下所示:
frameworks/base/core/java/com/android/internal/os/Zygotelnit.java
/**
* Prepare the arguments and forks for the system server process.
*
* Returns an {@code Runnable} that provides an entrypoint into system_server code in the
* child process, and {@code null} in the parent.
*/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
...
/* Hardcoded command line to start the system server */
// 创建 args 数组,这个数组用来保存启动SystemServer进程的启动参数
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); // ... 2
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
// 创建system_server进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities); // ... 3
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
// 当前代码逻辑运行在子进程中
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
// 处理system_server进程
return handleSystemServerProcess(parsedArgs); // ... 4
}
return null;
}
注释1处的代码用来创建 args 数组,这个数组用来保存启动SystemServer 进程的启动参数,其中可以看出SystemServer 进程的用户id 和用户组 id 被设置为1000 ,并且拥有用户组 1001~1010、1018、1021、1032 、3001~3010 的权限;进程名为 system_server ;启动的类名 com.android server.SystemServer 。在注释2处将 args 数组封装成 Arguments 对象并供注释3处的 forkSystemServer 函数调用 。在注释3处调用 Zygote.forkSystemServer 方法, 其内部会调用 nativeForkSystemServer 这个 Native 方怯, nativeForkSystemServer方法最终会通过fork函数在当前进程创建一个子进程,也就是SystemServer 进程,如果forkSystemServer 方法返回的 pid 的值为0 ,就表示当前的代码运行在新创建的子进程中, 则执行注释4处的 handleSystemServerProcess 来处理 SystemServer 进程。
3. runSelectloop
启动Systemserver 进程后,会执行ZygoteServer的runSelectLoop 方法来等待AMS的请求,代码如下所示:
frameworks/base/core/java/com/android/internal/os/ZygoteServe.java
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*/
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor()); // ... 1
peers.add(null);
// 无线循环等待AMS的请求
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 {
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this); // ... 5
if (mIsForkChild) {
// 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;
} else {
// 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) {
if (!mIsForkChild) {
// We're in the server so any exception here is one that has taken place
// pre-fork while processing commands or reading / writing from the
// control socket. Make a loud noise about any such exceptions so that
// we know exactly what failed and why.
Slog.e(TAG, "Exception executing zygote command: ", e);
// Make sure the socket is closed so that the other end knows immediately
// that something has gone wrong and doesn't time out waiting for a
// response.
ZygoteConnection conn = peers.remove(i);
conn.closeSocket();
fds.remove(i);
} else {
// We're in the child so any exception caught here has happened post
// fork and before we execute ActivityThread.main (or any other main()
// method). Log the details of the exception and bring down the process.
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
}
}
}
}
}
}
4. Zygote 进程启动总结
来源:oschina
链接:https://my.oschina.net/u/4355717/blog/4311233