在Android系统中,DVM,ART应用程序进程以及运行系统的关键服务System_server 进程都是由Zygote进程来创建的。我们将其称之为孵化器。它通过fork的形式创建应用程序进程和system_server 进程。由于zygote进程在启动的时候会创建DVM或者ART,因此通过fork而创建的应用程序进程或者system_server进程可以在内部获得一个dvm或者art的实例副本,不需要单独为每一个进程创建dvm或者art。
我们知道zygote进程是在init进程里面启动的,起初zygote进程的名字并不是叫做zygote,而是叫做app_process,这个名称是在Android.mk文件里面定义的,zygote进程其启动之后,Linux系统下的pctrl系统会调用app_process,将其名称换成了zygote。
在init.rc文件中采用import的方式引入zygote脚本。而zygote启动脚本都是通过Android初始化语言(Android Init Language)进行编写的。
import的位置:
android-9.0.0_r3/system/core/rootdir/init.rc
11 import /init.usb.configfs.rc
12 import /init.${ro.zygote}.rc ->根据系统属性 ro.zygote 进行定性
从上面的import语句,我们知道在启动zygote的时候,系统属性服务是已经启动起来了。
为什么要通过 系统属性 ro.zygote 来进行定位zygote启动文件呢,因为从Android 5.0 开始,Android 系统开始支持64位程序。Zygote 也就会有32位和64位的区别。所以利用系统属性 ro.zygote 来进行控制使用不同的脚本。ro.zygote 属性值有如下四种:
init.zygote32
init.zygote32_64
init.zygote64
init.zygote64_32
由此可以看出代码中会存在如下几个zygote文件:
/android-9.0.0_r3/system/core/rootdir/
init.zygote32.rc H A D 12-一月-2019 511
init.zygote32_64.rc H A D 12-一月-2019 853
init.zygote64.rc H A D 12-一月-2019 513
init.zygote64_32.rc H A D 12-一月-2019 875
比如我自己编译的aosp代码的 ro.zygote 的值为:
generic_x86_64:/ $ getprop ro.zygote zygote64_32
Android 初始化语音的service类型语句格式如下:
service []
表示支持纯32位程序,文件内容如下:
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
根据Service类型语句的格式,可以得知Zygote进程名称为zygote,执行程序为app_process ,class name为main。当zygote服务重启的时候,会重启 audioserver,cameraserver,media,netd,wificond
表示既支持32位应用程序,也支持64位应用程序。其内容如下:
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 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
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
这段代码中有两个service,则表明会启动两个zygote进程,一个为zygote 执行程序为 app_process32,作为主模式。另一个 zygote_secondary 执行的主程序为 app_process64 ,作为从/辅模式。
service zygote /system/bin/app_process64 -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
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 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
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 reserved_disk
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
从上面的service 的class我们知道,当在init进程启动class 为 main 的service的时候,就会启动zygote进程了。
而zygote进程其实际上是执行 app_process64/app_process32 的main函数。其最终是执行:frameworks/base/cmds/app_process/app_main.cpp 的main函数。
android-9.0.0_r3/frameworks/base/cmds/app_process/app_main.cpp
179 #if defined(__LP64__)
180 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
181 static const char ZYGOTE_NICE_NAME[] = "zygote64";
182 #else
183 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
184 static const char ZYGOTE_NICE_NAME[] = "zygote";
185 #endif
186
187 int main(int argc, char* const argv[])
...
278 while (i < argc) {
279 const char* arg = argv[i++];
280 if (strcmp(arg, "--zygote") == 0) { //1
281 zygote = true;
282 niceName = ZYGOTE_NICE_NAME;
283 } else if (strcmp(arg, "--start-system-server") == 0) { //2
284 startSystemServer = true;
285 } else if (strcmp(arg, "--application") == 0) {
286 application = true;
287 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
288 niceName.setTo(arg + 12);
289 } else if (strncmp(arg, "--", 2) != 0) {
290 className.setTo(arg);
291 break;
292 } else {
293 --i;
294 break;
295 }
296 }
...
323 if (startSystemServer) { //3
324 args.add(String8("start-system-server"));
325 }
...
345 if (!niceName.isEmpty()) {
346 runtime.setArgv0(niceName.string(), true /* setProcName */);
//调用 AndroidRuntime.cpp 的 start 函数。
347 }
348
349 if (zygote) { //4
350 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
351 } else if (className) {
352 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
353 } else {
354 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
355 app_usage();
356 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
357 }
zygote都是通过fork自身来孵化新的进程的,比如system_server , 应用程序等,都是通过zygote fork孵化而来,所以在zygote的子进程中,都是可以进入到app_main.cpp 的main函数中来的。因此main函数中为了区分运行在哪个进程,对参数做了简要的区分,在注释1处判断参数中是否包含了–zygote,如果包含了则说明main函数是运行在zygote进程中的,并且将 zygote 设置为true。而注释2处则为了标明需要启动system_server,同时在注释3处将 start-system-server 添加到args中,以传递给runtime。
android-9.0.0_r3/frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) { //参照上面给runtime传递的start-system-server 参数
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { //启动java虚拟机
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) { //为java虚拟机注册jni方法。
ALOGE("Unable to register all android natives\n");
return;
}
...
classNameStr = env->NewStringUTF(className);
//从上面的分析中可以知道此处的 className 为com.android.internal.os.ZygoteInit
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);
//将传递过来的参数全部再次组装以传递为java框架层
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
//对className 进行重新组装,将classname中的 "." 换成 "/"
jclass startClass = env->FindClass(slashClassName);
// 通过 JNIEnv 找到对应的class。
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
//找到 zygote 的main方法
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
//调用 ZygoteInit中的main方法。
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
我们通过jni调用ZygoteInit的main方法后,Zygote便进入到了Java框架层里面了。在此前是还没有代码进入到Java框架层的。换一个说法是zygote开创了java框架层。
android-9.0.0_r3/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
...
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
//参数中有 start-system-server , 则需要启动 system_server
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = 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());
// SOCKET_NAME_ARG == "--socket-name=", 在启动zygote的service里面有这样的参数: --socket-name=zygote 以及: --socket-name=zygote_secondary
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...
zygoteServer.registerServerSocketFromEnv(socketName);
//创建一个server断的socket,此处如果是zygote线程,则 socketName 为 zygote,如果为 zygote_secondary 线程,则socketName为zygote_secondary
// 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);
//预加载类和资源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
//启动system_server 进程。
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
...
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
//等待着system_server 中的AMS通过socket连接zygote,以响应AMS要求创建应用程序的需求。
由上面的分析,大致可以得出ZygoteInit的main函数干了如下几个重要的事情:
android-9.0.0_r3/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM,
OsConstants.CAP_BLOCK_SUSPEND
);
/* Containers run without some capabilities, so drop any caps that are not available. */
StructCapUserHeader header = new StructCapUserHeader(
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
StructCapUserData[] data;
try {
data = Os.capget(header);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to capget()", ex);
}
capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
/* 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,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
//启动 system_server 的参数,设置uid,gid为1000
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
//fork 函数会返回两个值,如果 pid 为0,则标识当前执行的是子进程。handleSystemServerProcess 处理 system_server 该处理的事物。
}
return null;
}
android-9.0.0_r3/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
fds.add(mServerSocket.getFileDescriptor());
//mServerSocket 则为前面我们创建的zygote 服务端socket,通过getFileDescriptor主要得到socket的fd值,并将其添加到监听列表fds中。
peers.add(null);
while (true) {
//无限循环等待AMS请求,
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;
}
//代码能够运行到此处,说明zygote 与AMS之间已经有socket建立连接了。
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
//通过 acceptCommandPeer 函数,得到ZygoteConnection 进程与AMS进程建立的连接,并添加到socket连接列表 peers 中,注意,这里表明这是刚刚才建立socket连接,还并未有更实质的数据通信,实际的通信则应该是 i != 0 的情况。
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//i不等于0的情况,说明AMS向zygote发送了一个创建应用程序的请求。通过processOneCommand 创建实际的应用程序。
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
//创建新的进程
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;
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the Runnable
// is returned.
mIsForkChild = false;
}
}
}
}
}
此函数的内容不算多,逻辑也还算较清晰。
zygote启动做了大致如下几个事务: