zygote的意思为“受精卵”,名字很贴切,因为android好多系统级进程如SysteServer等都是zygote fork出来的进程从而载入的,下面我们结合代码理一下android zygote启动的流程。
Android底层的内核为linux,内核启动到用户空间后,启动一个init进程,该进程是一个可执行文件,就挂载在跟分区,init之于android相当于盘古级别的功能,init可执行程序会解析根分区下的rc初始化脚本,里边有关于zygote定义启动的入口:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。而class标示了某一类的service,种类有class main;class core;class later_start等,当执行class_main start 命令时,会批量启动class main类型的service,其他的也类似。第三行有socket套接字的创建,即在/dev/socket目录下生成一个zygote节点,后续诸如AMS(ActivityManagerService)请求zygote为应用程序创建进程就是通过该socket进行交互。
最终的restart关键字表示在zygote进程重启的时候,需要执行的其他命令。下面开始具体的代码流:
1) frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
#ifdef __arm__
/*
* b/7188322 - Temporarily revert to the compat memory layout
* to avoid breaking third party apps.
*
* THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
*
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
* changes the kernel mapping from bottom up to top-down.
* This breaks some programs which improperly embed
* an out of date copy of Android's linker.
*/
char value[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", value, "");
bool is_qemu = (strcmp(value, "1") == 0);
if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
int current = personality(0xFFFFFFFF);
if ((current & ADDR_COMPAT_LAYOUT) == 0) {
personality(current | ADDR_COMPAT_LAYOUT);
setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
execv("/system/bin/app_process", argv);
return -1;
}
}
unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
#endif
// 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) {
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;
}
}
此方法的主要作用是创建AppRuntime变量并调用其start方法,从代码
class AppRuntime : public AndroidRuntime
{
......
}
AppRuntime继承自AndroidRuntime,而AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
static AndroidRuntime* gCurRuntime = NULL;
AndroidRuntime::AndroidRuntime() :
mExitWithoutCleanup(false)
{
......
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
gCurRuntime是一个静态全局的变量,当AppRunTime对象创建时,会调用AndroidRuntime的构造函数,而在AndroidRuntime的构造函数里,会将this指针保存在全局静态变量gCurRumtime中,如此,当其他地方在使用AppRumtime对象时,就可通过该文件中的同一个函数来获取静态对象的指针:
AndroidRuntime* AndroidRuntime::getRuntime()
{
return gCurRuntime;
}
因此,上文提到的调用AppRuntime的start方法,实则是调用AndroidRuntime的start方法。即runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
2)进入AndroidRuntime的start方法:
void AndroidRuntime::start(const char* className, const char* options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
if (!strcmp(className, "com.android.internal.os.ZygoteInit")) {
removeHprofEmptyFile();
}
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (strcmp(options, "start-system-server") == 0) {
/* 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)));
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) { //启动虚拟机
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) { //注册native层的jni接口
ALOGE("Unable to register all android natives\n");
return;
}
/*
* 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.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray, 1, optionsStr);
/*
* 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 {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main", //找到所传参数类(com.android.internal.os.ZygoteInit)中的main方法
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray); //调用前文找到的main方法。
#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");
}
3) ZygoteInit.main(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)
public class ZygoteInit {
......
public static void main(String argv[]) {
try {
/// M: Added for BOOTPROF
//MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable"));
MTPROF_DISABLE = false;
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
......
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
......
}
}
......
}
主要功能为红标部分的函数调用,第一个是注册zygote和AMS交互的socket节点;第二个是启动SystemServer;第三个循环侦听第一步创建的socket节点,侦听AMS与之交互的请求。
4)ZygoteInit.registerZygoteSocket();
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(
ANDROID_SOCKET_ENV + " unset or invalid", ex);
}
try {
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
这个socket接口是通过文件描述符来创建的,而文件描述符是通过ANDROID_SOCKET_ENV环境变量获取的,
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
这个环境变量是由init进程设置进去的,在此不再做init.c代码的具体分析,只讲流程是通过service_start()方法来解析执行initrc中的service,每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:
- static void publish_socket(const char *name, int fd)
- {
- char key[64] = ANDROID_SOCKET_ENV_PREFIX;
- char val[64];
- strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
- name,
- sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
- snprintf(val, sizeof(val), "%d", fd);
- add_environment(key, val);
- /* make sure we don't close-on-exec */
- fcntl(fd, F_SETFD, 0);
- }
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了,比如ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:
- public class Process {
- ......
- private static void openZygoteSocketIfNeeded()
- throws ZygoteStartFailedEx {
- ......
- for (int retry = 0
- ; (sZygoteSocket == null) && (retry < (retryCount + 1))
- ; retry++ ) {
- ......
- try {
- sZygoteSocket = new LocalSocket();
- sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
- LocalSocketAddress.Namespace.RESERVED));
- sZygoteInputStream
- = new DataInputStream(sZygoteSocket.getInputStream());
- sZygoteWriter =
- new BufferedWriter(
- new OutputStreamWriter(
- sZygoteSocket.getOutputStream()),
- 256);
- ......
- } catch (IOException ex) {
- ......
- }
- }
- ......
- }
- ......
- }
- public class Process {
- ......
- private static final String ZYGOTE_SOCKET = "zygote";
- ......
- }
后面接前文书,讲startSystemServer。
5) ZygoteInit.startSystemServer
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
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_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* 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,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
......
/* Request to fork the system server process */
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;
}
zygote通过fork一个新的进程来启动SystemServer组件,返回值pid=0即子进程会执行handleSystemServerProcess方法。
6) ZygoteInit.handleSystemServerProcess
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket(); //子进程并不需要之前创建的/dev/socket/zygote套接字节点,因此关闭
// 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);
}
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); //更近一步启动执行SystemServer组件的工作。
}
/* should never reach here */
}
7) RuntimeInit.zygoteInit(frameworks/base/core/java/com/android/internal/os/RuntimeInit.java)
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);
}
这个函数会执行两个操作,一个是调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了,另一个是调用上面5)传进来的com.android.server.SystemServer类的main函数。
8) nativeZygoteInit方法是一个native层的方法,在AndroidRuntime.cpp中实现,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。
9) 最后就到了applicationInit方法,定义在RuntimeInit.java类中。
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
......
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
红标部分是关键,会执行com.android.server.SystemServer类的main函数。
10) 开始上一步的入口函数,该函数定义在framework/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
......
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
nativeInit(); //具体native层的实现只是开启了SensorService实例。
......
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
这个版本的该方法较之与之前的版本改动较大,没有了init1和init2方法,实则是将两方法直接在main里边实现了,首先loadLibrary接口加载android_servers的native部分,然后创建ServerThread();再之后的initAndLoop()就是对系统各种Service的启动及注册操作的实现。系统级的Service启动注册完成之后,层层递退,回到第三步中的 runSelectLoop(); 开始循环等待响应AMS创建进程的请求了。
综上,大概流程如下:
Init进程---> Zygote ---> 启动框架层的进程和服务以及进程运行环境初始化 ---> Fork SystemServer进程 (启动系统万千重要服务WMS,AMS,PMS...)---> AMS通过socket与等待请求的Zygote交互,创建新的应用程序进程