我们知道,Android系统是基于Linux内核的。Linux中,所有的进程都是由init进程创建出来的,即所有的进程都是直接或间接被init进程fork产生的。Android进程的孵化器Zygote同样如此,它在系统启动过程中,被init进程创建出来。Android系统启动时,会解析init.rc初始化文件,我们先看init.rc中对Zygote配置文件的处理:
import /init.${ro.zygote}.rc
可以看到,此处配置文件的导入,是由ro.zygote属性控制的,由此来引入不同的文件。出现这种情况的原因是,Android 5.0以后,Android开始支持64位编译,Zygote进程也随之引入了32/64位的区别。所以,这里通过ro.zygote属性来控制启动不同版本的Zygote进程。
ro.zygote属性会有四种不同的值:
在init.rc同级目录下一共4个和Zygote进程有关的rc配置文件:
双模式下,Zygote的配置文件下会有两个服务声明,这里以init.zygote64_32.rc为例:
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
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
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
这两个服务声明最大的区别就是对应的可执行文件不一样。我们分析还是以纯32位模式为例,来看Zygote进程的启动过程。
纯32位模式下启动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告诉我们要创建一个名为Zygote的进程,并通过应用程序/system/bin/app_process来启动它;之后的内容是此次启动传入的参数:
socket关键字说明该进程需要创建一个套接字资源用于进程间通信,类型是unix domain socket,权限设置为660。onrestart关键字描述的都是该进程重启时需要执行的命令操作。
这里再介绍下app_process启动参数的格式:
在Init进程解析init.rc时,会解析并启动这个服务,最后通过系统调用exec()去执行zygote进程对应的应用程序。
它对应的文件是/frameworks/base/cmds/app_process/app_main.cpp;直接看它的main()函数:
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
}
//AppRuntime是AndroidRuntime的子类,这里初始化runtime对象时Androidruntime中的gCurRuntime变量会被初始化为AppRuntime对象:runtime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {//忽略第一个参数:-Xzygote
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;
}
}
Vector args;//启动Zygote进程时使用的参数列表
if (!className.isEmpty()) {//非Zygote模式
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);//如果不是zygote模式,则把要启动的Java类的名字保存到mClassName字段中
} else {//Zygote模式
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));//添加参数
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);//添加参数
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));//添加剩余的参数
}
}
if (!niceName.isEmpty()) {//设置进程名
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
if (zygote) {//zygote为TRUE
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//附带参数列表,在Zygote模式下,同过AndroidRuntime::start()启动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.");
return 10;
}
}
首先我们创建了一个AppRuntime实例runtime,它是AndroidRuntime的子类,重写了一些AndroidRuntime的方法。
app_process除了能启动Zygote进程外,还能启动某个系统的Java类(非zygote模式下)。我们经常使用的"am"命令就是通过app_process实现的。
runtime.start()实际是调用父类的同名方法AndroidRuntime::start()函数,分析它是怎么启动ZygoteInit的:
/*
* 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& 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) {
/* 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)));
}
}
//获取系统根目录,缺省是/system,如果没有/system目录,Zygote进程就会终止。系统目录是在Init进程中创建的
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, zygote) != 0) {//1、启动虚拟机
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) { //2、注册所需的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;
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.
*/
char* slashClassName = toSlashClassName(className);//com.android.internal.os.ZygoteInit
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",
"([Ljava/lang/String;)V");//通过JNI获取com.android.internal.os.ZygoteInit类的main()方法的jmethodID值
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);//通过JNI调用com.android.internal.os.ZygoteInit类的main()方法,进入Java层代码
#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");
}
AndroidRuntime是Android底层一个很重要的类,它负责启动JVM和Java类。AndroidRuntime在一个进程中只会有一个实例,在构造时,它的实例会保存在全局变量gCurRuntime中。
在start()函数中首先会获取系统根目录,然后调用startVMm()启动虚拟机。onVmCreated()函数在zygote模式下,并没有实际用处,但我们还是有必要看下它的处理,该函数定义在AppRuntime中:
virtual void onVmCreated(JNIEnv* env)
{
if (mClassName.isEmpty()) {//zygote模式下,mClassName为空,直接return
return; // Zygote. Nothing to do here.
}
/*
* This is a little awkward because the JNI FindClass call uses the
* class loader associated with the native method we're executing in.
* If called in onStarted (from RuntimeInit.finishInit because we're
* launching "am", for example), FindClass would see that we're calling
* from a boot class' native method, and so wouldn't look for the class
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
* because the "am" classes are not boot classes.
*
* The easiest fix is to call FindClass here, early on before we start
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
char* slashClassName = toSlashClassName(mClassName.string());//转换Java类的路径字符串
mClass = env->FindClass(slashClassName);//在当前的虚拟机环境下,根据类名查找这个类
if (mClass == NULL) {
ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
}
free(slashClassName);
mClass = reinterpret_cast(env->NewGlobalRef(mClass));
}
如果当前的启动模式不是zygote,那我们在通过app_process启动某个类时会为它指定一个要启动的类。首先,会转换指定的类的路径名,并在当前的虚拟机环境下查找这个类。这表明app_process将要调用的Java类必须是系统类。如果当前的启动模式是zygote,则直接返回。随后调用startReg()注册系统的JNI函数。
最后会将启动类用到的参数封装到strArray数组,并通过JNI的方式在native代码中直接调用ZygoteInit.java的main()函数,处理流程转而进入Java层。
ZygoteInit类是zygote进程的启动类,看它的main()函数:
public static void main(String argv[]) {
try {
RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true; //该标志为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());//值为zygote
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
registerZygoteSocket(socketName); // 1、创建socket,用来与ActivityManagerService进行通信
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(); // 2、预加载资源文件
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gcAndFinalize();
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
if (startSystemServer) {
startSystemServer(abiList, socketName); // 3、启动system_server进程
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList); // 4、开启一个循环,处理ActivityManagerService创建应用进程的请求
closeServerSocket(); // 程序退出时,清除socket资源
} catch (MethodAndArgsCaller caller) {
caller.run(); // 5、注意
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
代码中共标记出了5个较为重要的处理过程,下面一一分析。
(1)、registerZygoteSocket(socketName)
registerZygoteSocket()函数会注册Zygote的socket监听端口,用来接收启动应用程序的消息,查看其代码处理:
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;// fullSocketName:ANDROID_SOCKET_zygote
try {
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);//将该fd保存到descriptor中
sServerSocket = new LocalServerSocket(fd);//用该文件描述符创建一个LocalServerSocket对象,并开始监听该socket
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
从系统环境变量中获取到“ANDROID_SOCKET_zygote”这个socket对应的文件描述符,创建LocalServerSocket对象并监听该socket;此时名为zygote的socket就可以接收消息了。细心地人可能发现了,在我们的分析过程中并没有看到socket和Zygote进程的创建过程。其实这个过程在init.cpp解析init.rc文件时,已经处理完成了。下面来看这一部分内容。
系统启动解析init.rc时,每当碰到一个由service关键字声明的服务,就会给他创建一个进程、并初始化该服务相关的资源;这些资源就包括socket的创建。
在init.cpp中,void service_start(struct service *svc, const char *dynamic_args)函数负责启动每个声明的service服务,我们提出一段重要的处理过程:
pid_t pid = fork();//创建一个进程
if (pid == 0) {
struct socketinfo *si;
struct svcenvinfo *ei;
char tmp[32];
int fd, sz;
umask(077);
if (properties_initialized()) {
get_property_workspace(&fd, &sz);
snprintf(tmp, sizeof(tmp), "%d,%d", dup(fd), sz);
add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
}
for (ei = svc->envvars; ei; ei = ei->next)
add_environment(ei->name, ei->value);
for (si = svc->sockets; si; si = si->next) { //socket创建
int socket_type = (
!strcmp(si->type, "stream") ? SOCK_STREAM :
(!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
int s = create_socket(si->name, socket_type,
si->perm, si->uid, si->gid, si->socketcon ?: scon);
if (s >= 0) {
publish_socket(si->name, s);//socket发布
}
}
...
}
当系统为每个service通过调用fork()创建进程时,如果发现需要创建socket,它就会通过调用create_socket()创建一个socket:
/*
* create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
* ("/dev/socket") as dictated in init.rc. This socket is inherited by the
* daemon. We communicate the file descriptor's value via the environment
* variable ANDROID_SOCKET_ENV_PREFIX ("ANDROID_SOCKET_foo").
*/
int create_socket(const char *name, int type, mode_t perm, uid_t uid,
gid_t gid, const char *socketcon)
{
struct sockaddr_un addr;
int fd, ret;
char *filecon;
if (socketcon)
setsockcreatecon(socketcon);
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
return -1;
}
if (socketcon)
setsockcreatecon(NULL);
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
name);//设置此socket的地址
ret = unlink(addr.sun_path);
if (ret != 0 && errno != ENOENT) {
ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
goto out_close;
}
filecon = NULL;
if (sehandle) {
ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
if (ret == 0)
setfscreatecon(filecon);
}
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));//绑定该socket,启动listen在ZygoteInit::registerZygoteSocket()处理
if (ret) {
ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
goto out_unlink;
}
setfscreatecon(NULL);
freecon(filecon);
chown(addr.sun_path, uid, gid);
chmod(addr.sun_path, perm);
INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
addr.sun_path, perm, uid, gid);
return fd;//返回该socket的文件描述符
out_unlink:
unlink(addr.sun_path);
out_close:
close(fd);
return -1;
}
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);//ANDROID_SOCKET_zygote -- socket的文件描述符
/* make sure we don't close-on-exec */
fcntl(fd, F_SETFD, 0);
}
到这里,socket的创建、注册处理流程就联系起来了。
ANDROID_SOCKET_ENV_PREFIX、ANDROID_SOCKET_DIR两个宏定义在/system/core/include/cutils/Socket.h中:
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
#define ANDROID_SOCKET_DIR "/dev/socket"
(2)、preload()
preload()函数用于加载系统资源,包括预加载系统类、Framework资源和OpenGL资源等,它的处理如下:
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses();//加载/system/etc/preloaded-classes和framework.jar中的类资源
preloadResources();
preloadOpenGL();
preloadSharedLibraries();
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
Log.d(TAG, "end preload");
}
这里调用了5个函数去加载需要使用的类资源、图片资源、库资源等。这几个函数功能单一,我们可以自己阅读代码;这里就不详述了。但由于这部分内容涉及到很多I/O操作,而且加载的资源较多,会影响Android系统启动的时间。一些开机时间优化就是在这一部分处理的。
(3)、startSystemServer()
startSystemServer()函数用于启动system_server进程,它的具体处理如下:
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
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,1021,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",/*指明需要启动的进程的主类入口*/
};//创建system_server的参数列表。设置了进程的uid、gid和进程名
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 */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);//根据参数,为systemserver创建进程
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {//子进程,即system_server进程
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);//进程创建完毕后,调用该函数进一步处理
}
return true;//函数返回之后,重新返回到ZygoteInit.main()中,即进入Zygote父进程中
}
首先根据设置的参数列表创建system_server进程,然后在子进程中调用handleSystemServerProcess()做进一步处理:
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();//根据fork()机制,system_server是zygote的子进程,它也拥有zygote这个socket资源;但由于system_server不需要使用socket,这里将它关闭
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);//system_server
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);//com.android.server.SystemServer
}
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//重要
}
/* should never reach here */
}
直接查看函数末尾调用RuntimeInit.zygoteInit()函数:
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.
*
* Current recognized args:
*
* -
[--]
*
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();//通用的初始化部分,包括设置默认的uncaught exception handler等
nativeZygoteInit();//调用AppRuntime.cpp::onZygoteInit(),开启线程池,用于Binder通信
applicationInit(targetSdkVersion, argv, classLoader);//通过反射调用SystemServer.java的main函数
}
函数主要做了三个个处理:通用初始化部分;native层开启线程池,用于Binder通信;
private static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
/*
* Sets handler for java.util.logging to use Android log facilities.
* The odd "new instance-and-then-throw-away" is a mirror of how
* the "java.util.logging.config.class" system property works. We
* can't use the system property here since the logger has almost
* certainly already been initialized.
*/
LogManager.getLogManager().reset();
new AndroidConfig();
/*
* Sets the default HTTP User-Agent used by HttpURLConnection.
*/
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
/*
* Wire socket tagging to traffic stats.
*/
NetworkManagementSocketTagger.install();
/*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
* consequences, so it's not something you want to do always.
*/
String trace = SystemProperties.get("ro.kernel.android.tracing");
if (trace.equals("1")) {
Slog.i(TAG, "NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}
initialized = true;
}
通用部分的初始化,包括设置默认的uncaught exception handler(UncaughtHandler类);设置默认时区;为HttpURLConnection准备默认的Http User-Agent;开启trace模式等。
nativeZygoteInit()是重要的本地初始化函数,根据JNI实现其最终调用:
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();//gCurRuntime实际指向AndroidRuntime的子类AppRuntime实例,即调用AppRuntime::onZygoteInit()
}
virtual void AppRuntime::onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();//开启Binder线程池以保证其他进程可以正确访问到Zygote所提供的服务
}
启动线程池,用于Binder通信。然后进入applicationInit():
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);//通过反射调用SystemServer.java的main方法
}
再看invokeStaticMain():
/**
* Invokes a static "main(argv[]) method on class "className".
* Converts various failing exceptions into RuntimeExceptions, with
* the assumption that they will then cause the VM instance to exit.
*
* @param className Fully-qualified class name
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });//获取SystemServer.java的main()函数的域名,但并没有立即调用main函数;
} 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.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);//在ZygoteInit.java的main()中第5步处理时,调用SystemServer.java的main()函数
}
通过ZygoteInit.MethodAndArgsCaller异常的处理来调用SystemServer.java的main()函数启动各个系统服务,看MethodAndArgsCaller的定义:
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
由代码注释可知:这种调用方式会清理堆栈,可以让SystemServer.java的main函数认为自己是system_server进程的入口,虽然这之前已经做了大量的工作。
(4)、 runSelectLoop()
system_server进程处理完毕后,函数调用重新返回到ZygoteInit.main()中。Zygote进程此时会进入一个loop循环,等待处理来自运行在system_server中的AMS的创建应用进程的请求。runSelectLoop()函数会进入监听和接收socket消息的循环之中,它的处理如下:
/**
* 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.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);//添加null,是为了保持fds和peers的一致性(对应Zygote Server Socket);可以看到后面处理中,添加/移除操作都是成对出现的
while (true) {
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;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
acceptCommandPeer()函数会和客户端建立一个socket连接;而ZygoteConnection对象可以进行请求通信。如果ActivityManagerService发送的创建新应用进程的请求在此处收到后,就会进入ZygoteConnection::runOnce()处理。
/**
* Reads one start command from the command socket. If successful,
* a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
* exception is thrown in that child while in the parent process,
* the method returns normally. On failure, the child is not
* spawned and messages are printed to the log and stderr. Returns
* a boolean status value indicating whether an end-of-file on the command
* socket has been encountered.
*
* @return false if command socket should continue to be read from, or
* true if an end-of-file has been encountered.
* @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
* method in child process
*/
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();//读取创建进程时传递的参数
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
if (args == null) {//参数读取失败时,会关掉当次socket连接
// EOF reached.
closeSocket();
return true;
}
/** the stderr of the most recent request, if avail */
PrintStream newStderr = null;
if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(
new FileOutputStream(descriptors[2]));
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
parsedArgs = new Arguments(args);//将读到的参数保存到Arguments对象中
if (parsedArgs.abiListQuery) {
return handleAbiListQuery();
}
if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: " +
"permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
}
applyUidSecurityPolicy(parsedArgs, peer);
applyInvokeWithSecurityPolicy(parsedArgs, peer);
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
if (parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
}
/**
* In order to avoid leaking descriptors to the Zygote child,
* the native code must close the two Zygote socket descriptors
* in the child process before it switches from Zygote-root to
* the UID and privileges of the application being launched.
*
* In order to avoid "bad file descriptor" errors when the
* two LocalSocket objects are closed, the Posix file
* descriptors are released via a dup2() call which closes
* the socket and substitutes an open descriptor to /dev/null.
*/
int [] fdsToClose = { -1, -1 };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
fdsToClose[0] = fd.getInt$();
}
fd = ZygoteInit.getServerSocketFileDescriptor();
if (fd != null) {
fdsToClose[1] = fd.getInt$();
}
fd = null;
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);//调用forkAndSpecialize()函数创建新进程
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
logAndPrintError(newStderr, "Invalid zygote arguments", ex);
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
}
try {
if (pid == 0) {//pid = 0,表示在新创建的子进程中
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);//调用handleChildProc()来启动子进程
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
runOnce()的主要工作就是会为这个请求fork一个新的进程,并做一些其他的处理。这一部分的内容会在后续分析Application启动时,再做详细介绍。
(5)、MethodAndArgsCaller异常处理
我们退回到ZygoteInit::main()函数中,看MethodAndArgsCaller异常的捕获处理过程:
catch (MethodAndArgsCaller caller) {
caller.run(); // 5、注意
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });//调用mMethod本身代表的方法
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
run()方法中通过invoke()调用SystemServer.java的main()方法:
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
SystemServer.run()方法中做了大量的工作,其中就包括启动各种重要的Android系统服务,如PackageManagerService、PowerManagerService等,run()函数的实现如下:
private void run() {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it shortly.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {//如果系统时间不正确,则调整系统时间
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
// If the system has "persist.sys.language" and friends set, replace them with
// "persist.sys.locale". Note that the default locale at this point is calculated
// using the "-Duser.locale" command line flag. That flag is usually populated by
// AndroidRuntime using the same set of system properties, but only the system_server
// and system apps are allowed to set them.
//
// NOTE: Most changes made here will need an equivalent change to
// core/jni/AndroidRuntime.cpp
if (!SystemProperties.get("persist.sys.language").isEmpty()) {
final String languageTag = Locale.getDefault().toLanguageTag();
SystemProperties.set("persist.sys.locale", languageTag);
SystemProperties.set("persist.sys.language", "");
SystemProperties.set("persist.sys.country", "");
SystemProperties.set("persist.sys.localevar", "");
}
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
// property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
// the property. http://b/11463182
//设置当前的虚拟机的运行库路径
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Enable the sampling profiler.
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
mProfilerSnapshotTimer = new Timer();
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
// Initialize native services.
System.loadLibrary("android_servers");//装载libandroid_servers.so库
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
createSystemContext();//初始化系统Context对象,这块详细内容会在分析ActivityManagerService时介绍
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
SystemServer::run()函数中,重要的服务启动操作都工作在主线程中,并且最后会开启一个消息循环。
其中:
// Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
会启动Android系统中各种重要的系统服务。到此,Zygote进程的启动过程就结束了。