1.  init 根据init.rc 运行 app_process, 并携带‘--zygote' 和 ’--startSystemServer' 参数。

2.  AndroidRuntime.cpp::start() 里将启动JavaVM,并且注册所有framework相关的系统JNI接口。

3.  第一次进入Java世界,运行ZygoteInit.java::main() 函数初始化Zygote. Zygote 并创建Socket的server 端。

4.  然后fork一个新的进程并在新进程里初始化SystemServer. Fork之前,Zygote是preload常用的Java类库,以及系统的resources,同时GC()清理内存空间,为子进程省去重复的工作。

5.  SystemServer 里将所有的系统Service初始化,包括ActivityManager 和 WindowManager, 他们是应用程序运行起来的前提。

6.  与此同时,Zygote监听服务端Socket,等待新的应用启动请求。

7.  ActivityManager ready 之后寻找系统的“Startup” Application, 将请求发给Zygote。

8.  Zygote收到请求后,fork出一个新的进程。

9.  Zygote监听并处理SystemServer 的 SIGCHID 信号,一旦System Server崩溃,立即将自己杀死。init会重启Zygote.

以下内容主要针对上面的介绍展开,附上两张图,这两张图片包含了我们今天要讲解的所有内容

zygote启动流程图

zygote相关的所有类的结构图

  这里要讲的是zygote启动流程所以主要针对第一张图来讲 ,关于这部分内容,个人觉得,对于想自己开发系统的人来说是很有帮助,每个系统首先启动的便是孵化器进程,以及server监听进程。

一 概念

  在Android系统中,所有的应用程序和系统服务进程,都是Zygote负责创建的,因此,Zygote也就被成为进程孵化器。Zygote进程是通过复制自身的方式来创建System进程和应用程序进程的。 Zygote会在系统启动时创建一个虚拟机实例,因此,通过复制Zygote进程而得到的System进程和应用程序进程可以快速第在内部获得一个虚拟机实例拷贝。  

  Zygote进程启动完成之后,会将system进程启动起来,以便它可以将系统的关键服务启动起来。例如AMS ContentService 和WMS及PMS等。

二 Zygote启动  

  Zygote进程在init进程启动过程中被以service服务的形式启动,代码如下:./system/core/rootdir/init.zygote32.rc的service_start()

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  ...
 socket zygote stream 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的参数。

接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。

最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。

关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。

了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。

 在继续分析Zygote进程启动的过程之前,我们先来看看它的启动序列图: 

下面我们就详细分析每一个步骤。

        Step 1. app_process.main

这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, , , , ) < ) {
// 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 ;
}
} AppRuntime runtime(argv[], 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 = ; i < argc; i++) {
if (argv[i][] != '-') {
break;
}
if (argv[i][] == '-' && argv[i][] == ) {
++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) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == ) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == ) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == ) {
application = true;
} else if (strncmp(arg, "--nice-name=", ) == ) {
niceName.setTo(arg + );
} else if (strncmp(arg, "--", ) != ) {
className.setTo(arg);
break;
} else {
--i;
break;
}
} Vector<String8> args;
if (!className.isEmpty()) {
// 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);
} else {
// 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) == ) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return ;
} 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) {
runtime.start("com.android.internal.os.ZygoteInit", args, 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 ;
}
}

  这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。它同样是在frameworks/base/cmds/app_process/app_main.cpp文件中定义:

class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
} void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
mClassName = className;
for (int i = ; i < argc; ++i) {
mArgs.add(String8(argv[i]));
}
} virtual void onVmCreated(JNIEnv* env)
{
if (mClassName.isEmpty()) {
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());
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
}
free(slashClassName); mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
} virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs); IPCThreadState::self()->stopProcess();
} virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
} virtual void onExit(int code)
{
if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
} AndroidRuntime::onExit(code);
} String8 mClassName;
Vector<String8> mArgs;
jclass mClass;
}; }

  它继承于AndroidRuntime类, AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

static AndroidRuntime* gCurRuntime = NULL;
... AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
mExitWithoutCleanup(false),
mArgBlockStart(argBlockStart),
mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
// There is also a global font cache, but its budget is specified by
// SK_DEFAULT_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_FONT_CACHE_LIMIT. // Pre-allocate enough space to hold a fair number of options.
mOptions.setCapacity(); assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}

  当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的这个函数来获取这个对象的指针:

AndroidRuntime* AndroidRuntime::getRuntime()
{
return gCurRuntime;
}

  回到上面的main函数中,由于我们在init.rc文件中,设置了app_process启动参数--zygote和--start-system-server,因此,在main函数里面,最终会执行下面语句:

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

  这里的参数startSystemServer为true,表示要启动SystemServer组件。由于AppRuntime没有实现自己的start函数,它继承了父类AndroidRuntime的start函数,因此,下面会执行AndroidRuntime类的start函数。

        Step 2. AndroidRuntime.start

这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

/*
* 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)
{
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 = ; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = ;
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, );
} //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) != ) {
return;
}
onVmCreated(env); /*
* Register android functions.
*/
if (startReg(env) < ) {
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() + , stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, , classNameStr); for (size_t i = ; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + , 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",
"([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); #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() != )
ALOGW("Warning: VM did not shut down cleanly\n");
}

  这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

 Step 3. ZygoteInit.main

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    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;
} 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());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
} if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
} registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
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);
} Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList); closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}

  它主要作了三件事情,一个调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯,二是调用startSystemServer函数来启动SystemServer组件,三是调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

Step 4. ZygoteInit.registerZygoteSocket

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

  private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
} try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}

  这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,它定义为:

public class ZygoteInit {
...... private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote"; ......
}

  那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.cpp文件中,是由service_start函数来解释init.rc文件中的service命令的:

void service_start(struct service *svc, const char *dynamic_args)
{
// Starting a service removes it from the disabled or reset state and
// immediately takes it out of the restarting state if it was in there.
svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
svc->time_started = ; // Running processes require no additional work --- if they're in the
// process of exiting, we've ensured that they will immediately restart
// on exit, unless they are ONESHOT.
if (svc->flags & SVC_RUNNING) {
return;
} bool needs_console = (svc->flags & SVC_CONSOLE);
if (needs_console && !have_console) {
ERROR("service '%s' requires console\n", svc->name);
svc->flags |= SVC_DISABLED;
return;
} struct stat s;
if (stat(svc->args[], &s) != ) {
ERROR("cannot find '%s', disabling '%s'\n", svc->args[], svc->name);
svc->flags |= SVC_DISABLED;
return;
} if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
svc->args[]);
svc->flags |= SVC_DISABLED;
return;
} char* scon = NULL;
if (is_selinux_enabled() > ) {
if (svc->seclabel) {
scon = strdup(svc->seclabel);
if (!scon) {
ERROR("Out of memory while starting '%s'\n", svc->name);
return;
}
} else {
char *mycon = NULL, *fcon = NULL; INFO("computing context for service '%s'\n", svc->args[]);
int rc = getcon(&mycon);
if (rc < ) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
} rc = getfilecon(svc->args[], &fcon);
if (rc < ) {
ERROR("could not get context while starting '%s'\n", svc->name);
freecon(mycon);
return;
} rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
if (rc == && !strcmp(scon, mycon)) {
ERROR("Warning! Service %s needs a SELinux domain defined; please fix!\n", svc->name);
}
freecon(mycon);
freecon(fcon);
if (rc < ) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
}
}
} NOTICE("Starting service '%s'...\n", svc->name); pid_t pid = fork();
if (pid == ) {
struct socketinfo *si;
struct svcenvinfo *ei;
char tmp[];
int fd, sz; umask();
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) {
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 >= ) {
publish_socket(si->name, s);
}
} freecon(scon);
scon = NULL; if (svc->writepid_files_) {
std::string pid_str = android::base::StringPrintf("%d", pid);
for (auto& file : *svc->writepid_files_) {
if (!android::base::WriteStringToFile(pid_str, file)) {
ERROR("couldn't write %s to %s: %s\n",
pid_str.c_str(), file.c_str(), strerror(errno));
}
}
} if (svc->ioprio_class != IoSchedClass_NONE) {
if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
}
} if (needs_console) {
setsid();
open_console();
} else {
zap_stdio();
} if (false) {
for (size_t n = ; svc->args[n]; n++) {
INFO("args[%zu] = '%s'\n", n, svc->args[n]);
}
for (size_t n = ; ENV[n]; n++) {
INFO("env[%zu] = '%s'\n", n, ENV[n]);
}
} setpgid(, getpid()); // As requested, set our gid, supplemental gids, and uid.
if (svc->gid) {
if (setgid(svc->gid) != ) {
ERROR("setgid failed: %s\n", strerror(errno));
_exit();
}
}
if (svc->nr_supp_gids) {
if (setgroups(svc->nr_supp_gids, svc->supp_gids) != ) {
ERROR("setgroups failed: %s\n", strerror(errno));
_exit();
}
}
if (svc->uid) {
if (setuid(svc->uid) != ) {
ERROR("setuid failed: %s\n", strerror(errno));
_exit();
}
}
if (svc->seclabel) {
if (is_selinux_enabled() > && setexeccon(svc->seclabel) < ) {
ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
_exit();
}
} if (!dynamic_args) {
if (execve(svc->args[], (char**) svc->args, (char**) ENV) < ) {
ERROR("cannot execve('%s'): %s\n", svc->args[], strerror(errno));
}
} else {
char *arg_ptrs[INIT_PARSER_MAXARGS+];
int arg_idx = svc->nargs;
char *tmp = strdup(dynamic_args);
char *next = tmp;
char *bword; /* Copy the static arguments */
memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *))); while((bword = strsep(&next, " "))) {
arg_ptrs[arg_idx++] = bword;
if (arg_idx == INIT_PARSER_MAXARGS)
break;
}
arg_ptrs[arg_idx] = NULL;
execve(svc->args[], (char**) arg_ptrs, (char**) ENV);
}
_exit();
} freecon(scon); if (pid < ) {
ERROR("failed to start '%s'\n", svc->name);
svc->pid = ;
return;
} svc->time_started = gettime();
svc->pid = pid;
svc->flags |= SVC_RUNNING; if ((svc->flags & SVC_EXEC) != ) {
INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
svc->pid, svc->uid, svc->gid, svc->nr_supp_gids,
svc->seclabel ? : "default");
waiting_for_exec = true;
} svc->NotifyStateChange("running");
}

  每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去:

static void publish_socket(const char *name, int fd)
{
char key[] = ANDROID_SOCKET_ENV_PREFIX;
char val[]; strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - ,
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, );
}

  这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:

#define ANDROID_SOCKET_ENV_PREFIX       "ANDROID_SOCKET_"
#define ANDROID_SOCKET_DIR "/dev/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的:frameworks/base/core/java/android/os/Process.java

  public static final String ZYGOTE_SOCKET = "zygote";
  /**
* Tries to open socket to Zygote process if not already open. If
* already open, does nothing. May block and retry.
*/
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
} if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
} // The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
} if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
} throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

ZYGOTE_SOCKET刚好就是对应/dev/socket目录下的zygote文件了。

Android系统中的socket机制和binder机制一样,都是可以用来进行进程间通信。

Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。

Step 5. ZygoteInit.startSystemServer
       这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    /**
* 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",
};
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);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
} /* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
} handleSystemServerProcess(parsedArgs);
} return true;
}

   这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

Step 6. ZygoteInit.handleSystemServerProcess
        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    /**
* Finish remaining work for the newly forked system server process.
*/
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.
Os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
} final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
} 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 */
}

  由于由Zygote进程创建的子进程会继承Zygote进程在前面Step 4中创建的Socket文件描述符,而这里的子进程又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

Step 7. RuntimeInit.zygoteInit

这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    /**
* 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.<p>
*
* Current recognized args:
* <ul>
* <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
* </ul>
*
* @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();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}

  这个函数会执行两个操作,一个是调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了,另一个是调用上面Step 5传进来的com.android.server.SystemServer类的main函数。

Step 8. RuntimeInit.nativeZygoteInit

这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

public class RuntimeInit {
...... public static final native void nativeZygoteInit(); ......
}

  这里可以看出,函数nativeZygoteInit是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。

回到Step 7中的RuntimeInit.nativeZygoteInit函数,下一步它就要执行com.android.server.SystemServer类的main函数了。

Step 9. SystemServer.main

这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:

    /**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
} 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"); // Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown(); // Initialize the system context.
createSystemContext(); // 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");
}

  这里执行完成后,层层返回,最后回到上面的Step 3中的ZygoteInit.main函数中,接下来它就要调用runSelectLoopMode函数进入一个无限循环在前面Step 4中创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程了。

Step 10. ZygoteInit.runSelectLoopMode

这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.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.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); fds.add(sServerSocket.getFileDescriptor());
peers.add(null); 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);
}
}
}
}
}

  这个函数就是在等待ActivityManagerService来连接这个Socket,然后调用ZygoteConnection.runOnce函数来创建新的应用程序。

这样,Zygote进程就启动完成了,学习到这里,我们终于都对Android系统中的进程有了一个深刻的认识了,这里总结一下:

1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。

2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。

3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。

Zygote及System进程启动的更多相关文章

  1. 笔记:Zygote和SystemServer进程启动过程

    简述 Android设备启动过程中,先是Linux内核加载完,接着Android中的第一个进程init启动,它会启动一些需要开机启动的进程. Zygote就是进程init启动起来的.Android中所 ...

  2. system进程启动普通用户进程调研

    system进程启动普通用户进程 关键函数是CreateProcessAsUser 主要思路是先取得目的用户的token,然后用上面的函数启动 1.从explorer中取token BOOL GetT ...

  3. Zygote和System进程的启动过程

    ##init脚本的启动 +------------+ +-------+ +-----------+ |Linux Kernel+--> |init.rc+-> |app_process| ...

  4. Zygote和System进程的启动过程、Android应用进程启动过程

    1.基本过程 init脚本的启动Zygote Zygote进程的启动 System进程的启动 Android应用进程启动过程 2.init脚本的启动 +------------+ +-------+ ...

  5. Android Zygote进程启动分析

    dvm,app进程,linux进程三者关系 DVM指 dalivk 的虚拟机.每一个 Android 应用程序都在它自己的进程中运行,都拥有一个独立的 Dalvik 虚拟机实例.而每一个 DVM 都是 ...

  6. 图解Android - Zygote, System Server 启动分析

    Init 是所有Linux程序的起点,而Zygote于Android,正如它的英文意思,是所有java程序的'孵化池'(玩过星际虫族的兄弟都晓得的).用ps 输出可以看到 >adb shell ...

  7. Android应用程序进程启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...

  8. Android系统启动流程(三)解析SystemServer进程启动过程

    1.Zygote启动SystemServer进程 在上一篇文章中我们讲到在ZygoteInit.java的startSystemServer函数中启动了SyetemServer进程,如下所示. fra ...

  9. Android系统启动流程(一)解析init进程启动过程

    整体流程大致如下:     1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ...

随机推荐

  1. 2019-04-04 Mybatis学习知识点

    1. 比较#和$的区别 #是占位符?,$是字符串拼接.因此使用$的时候,如果参数是字符串类型,那么要使用引号 尽量使用#而不是$ 当参数表示表名或列名的时候,只能使用$ 2. 多参数时候 配置文件中使 ...

  2. servlet(5) HttpSession

    Servlet 提供的 HttpSession 接口,提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式. Servlet 容器使用这个接口来创建一个 HTTP 客户端和 HTTP ...

  3. word里面对齐用Tab键

    1       Tab      组1 2             组2

  4. 常见的概率分布类型(Probability Distribution)

    统计学中最常见的几种概率分布分别是正态分布(normal distribution),t分布(t distribution),F分布(F distribution)和卡方分布(χ2 distribut ...

  5. ubuntu下使用ss-qt5

    第一步:.安装ss-qt5 通过PPA源安装,仅支持Ubuntu 14.04或更高版本. 打开终端 sudo add-apt-repository ppa:hzwhuang/ss-qt5 sudo a ...

  6. django rest framework authentication

    身份验证 身份验证是将传入请求与一组识别凭证(例如请求的用户或其签名的令牌)相关联的机制.然后,权限和限制策略可以使用这些凭据来确定请求是否应该被允许. REST framework 提供了许多开箱即 ...

  7. 我眼中的Adaboost

    步骤: def buildStump(dataArr,classLabels,D): 1.循环取出数据集中的一个特征(一列)输入 (for:) 2.循环调整阀值threshVal  (for:) 3, ...

  8. QTcpSever和QTcpSocket实现多线程客户端和服务端;

    QTcpServer提供了newConnection信号, 可以通过connect实现连接槽函数,利用nextPendingConnection 函数获取连接的QTcpSocket * :也可以继承Q ...

  9. atool-build 打包项目报JavaScript heap out of memory 错误

    出现这个问题的原因,是因为NodeJS给JavaScript设置了默认内存使用限制(32位系统下0.7GB,64位系统下1.4GB),就算我们的电脑内存是64GB的,在使用atool-build打包时 ...

  10. volatile&synchronized&diff

    1. 三大性质简介 在并发编程中分析线程安全的问题时往往需要切入点,那就是两大核心:JMM抽象内存模型以及happens-before规则(在这篇文章中已经经过了),三条性质:原子性,有序性和可见性. ...