在Android系统中,所有的应用程序和系统服务system server都是由zygote进程fork出来的。本文简单分析zygote的启动过程。
1、init.rc
init进程是linux系统启动的第一个进程,后续启动的所有进程都是init进程的直接或者间接fork出来的,zygote进程也是一样。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
# patch
#oneshot
这段脚本,将会启动一个名字未zygote的进程,可执行文件为/system/bin/app_process,传递的参数是-Xzygote /system/bin –zygote –start-system-server。socket配置则表示zygote进程需要一个命名未zygote的socket。onrestart配置则定义了zygote进程重启时需要执行的动作。
init.rc的解析过程,可以参考Android中init.rc文件的解析和Android init.rc文件解析过程详解(一) 等文章。解析过程的源码都在/system/core/init目录下,说明文件为readme.txt。
2、app_process.cpp
从init.rc的配置中,可以看到zygote是通过app_process启动的。它的源码位于/base/cmds/app_process/app_process.cpp。
int main(int argc, const char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char* argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} 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 = arg + 12;
} else {
className = arg;
break;
}
}
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) { // 启动参数包含了--zygote --start-system-server
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
在init.rc中已经配置了zygote进程启动参数:–zygote –start-system-server。所以此处zygote和startSystemServer都是true,最终调用了runtime.start(“com.android.internal.os.ZygoteInit”, “start-system-server”)。runtime是AppRuntime的实例,AppRuntime继承于AndroidRuntime。
3、AndroidRuntime.cpp
位于目录/frameworks/base/core/jni。
void AndroidRuntime::start(const char* className, const char* options)
{
// 。。。。省略,设置env等
/* start the virtual machine */
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) { // 启动vm
return;
}
onVmCreated(env); // vm启动完成的回调,AppRuntime里有具体的实现
/*
* Register android functions.
*/
if (startReg(env) < 0) { // 注册jni函数,
ALOGE("Unable to register all android natives\n");
return;
}
// 。。。。省略,查找java string类等
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到com.android.internal.os.ZygoteInit.java的main()函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// start class = com.android.internal.os.ZygoteInit,调用了该类的main函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
// 。。。。省略,清理工作
}
以上流程,简单来说,就是先启动了vm,注册jni函数,然后调用了com.android.internal.os.ZygoteInit.java的main()函数。启动vm时,会将很多system properties的配置作为参数。包括heap start size、heap size、heap growth limit、heap min / max free等等。注册的jni函数,包括了binder、media、assert、log、opengl、surface、graphics、db、net等等很多个模块的。最后调用了com.android.internal.os.ZygoteInit的main()函数。
4、ZygoteInit.java
位于/frameworks/base/core/java/com/android/internal/os/目录。
public static void main(String argv[]) {
try {
registerZygoteSocket(); // 启动socket
preload(); // 加载N个java类
// Do an initial gc to clean up after startup
gc();
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
// fork system server进程,并抛出一个MethodAndArgsCaller异常,
// caller.run()实际是调用了system server的main()函数。这样,就将
// java层的各个系统服务子模块的service启动起来了。
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) { // ZYGOTE_FORK_MODE = false
runForkMode();
} else {
runSelectLoopMode(); // zygote进程走此逻辑,socket select模式,non-block
}
closeServerSocket(); // 关闭socket
} catch (MethodAndArgsCaller caller) {
caller.run(); // system server进程会走此逻辑
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
ZygoteInit的main()函数主要做了4件事情:1、registerZygoteSocket(),使用系统变量ANDROID_SOCKET_zygote定义的fd,创建一个local server socket,和Activity manager service里的socket通讯;2、preload(),读取文件preloaded-classes中定义的所有类并加载,读取com.android.internal.R.array.preloaded_drawables和com.android.internal.R.array.preloaded_color_state_lists定义的所有资源文件并加载;3、startSystemServer(),使用一些参数启动system server进程。4、runSelectLoopMode(),将会在一个while循环中处理从ActivityManagerService中发送的请求。
以下是runSelectLoopMode()和startSystemServer()的代码。
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) { // while循环
int index;
// 。。。。省略,gc
try {
fdArray = fds.toArray(fdArray);
// jni代码执行select(fd...),当fd有数据时返回fd的index
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) { // 所有的请求都处理完成了
// 从server socket的accept()中获取新的连接
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
// ZygoteConnection.runOnce()将会调用Zygote.forkAndSpecialize()fork出一个新的进程
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* 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,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"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出一个system server进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
// set umask to 0077 so new files and directories will default to owner-only permissions.
Libcore.os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
// startSystemServer()的参数中并没有--invoke-with字段,所以此处invokeWith == null
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
}
5、RuntimeInit.java
位于目录/frameworks/base/core/java/com/android/internal/os/。
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// 对接system out/err流到android的log系统
redirectLogStreams();
// 1、设置线程的Thread.setDefaultUncaughtExceptionHandler(),异常时会想am报告,并杀掉进程
// 2、根据system properties设置时区等
// 3、UA等其它设置
commonInit();
// 先调用到了AndroidRuntime的onZygoteInit(),具体实现在app_process.cpp的内部类AppRuntime中,最终调用ProcessState.startThreadPool()
nativeZygoteInit();
// 先调用到了invokeStaticMain(),最终作用是调用com.android.server.SystemServer.java的main()函数,初始化java层的各个子系统service
applicationInit(targetSdkVersion, argv);
}
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
// 找到com.android.server.SystemServer类
try {
cl = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 找到com.android.server.SystemServer的main方法
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
// 主动抛出一个异常,在ZygoteInit的main()函数中捕获了该异常,在异常捕获中调用了m方
// 法,也就是调用了com.android.server.SystemServer的main()方法。system server
// 进程的逻辑流程结束,而zygote进程进入了runSelectLoopMode()流程。
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
6、Zygote.java
位于/libcore/dalvik/src/main/java/dalvik/system/目录。java层直接调用了native方法。这些native方法定义在/dalvik/vm/native/dalvik_system_Zygote.cpp中,主要就是根据传递的一些参数,最终调用系统的fork()方法创建一个子进程,有兴趣的话可以自行查看。
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
preFork(); // wait until all thread stopped ???
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
postFork();
return pid;
}
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName) {
preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName);
postFork();
return pid;
}
7、总结
1、init.rc先启动了zygote进程
2、zygote进程启动时,先创建了local server socket,预加载配置好的类和资源文件,gc,
再fork出system server进程,最后进入runSelectLoopMode(),接收socket命令,
fork出一个一个的应用进程。
3、system server进程在fork之后,先将log、timezone、thread、ua、binder等设置好,
然后进入com.android.server.SystemServer的main()方法,启动java层的所有的系
统服务子模块。而在启动的ActivityManagerService中,将会创建一个socket,负责和
zygote的server socket通讯,必要的时候,通过socket发送命令到zygote进程,而
zygote进程接收到命令后,将fork出一个一个的进程。