android 系统启动时调用的相关文件路径:
Z:\mocor_sc9820w_new\mocor_sc9820\system\core\rootdir\init.rc
Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\cmds\app_process\app_main.cpp
Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\core\jni\AndroidRuntime.cpp
Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
Z:\mocor_sc9820w_new\mocor_sc9820\system\core\init\init.c
Z:\mocor_sc9820w_new\mocor_sc9820\frameworks\base\services\java\com\android\server\SystemServer.java
C语言的入口函数:
int main(int argc, char* const argv[]) argc 参数的个数,argc 参数。
Java的入口函数:
public static void main(String argv[])没有返回值,必须为void。
android app 上层是java写的,通过编译,生成.class文件,class文件通过sdk包中的dex工具,将class文件转换为dex文件,运行在虚拟机上。应用程序通过binder ipc 访问系统服务,系统服务通过jni访问hal module用户空间部分设备,hal module通过设备文件访问内核空间设备驱动。
android 专用驱动是以Linux驱动的形式实现在linux内核空间,android专用驱动主要有:
1.高效的日志服务。
2.高效的进程间通信机制
3.以组件为目标的进程管理机制。
它的目的不是为了驱动硬件设备工作而是为了获得特权管理系统,它是为android runtime framework应用框架层服务。
AMS 启动一个应用程序的时候,会通过socket与zygote进程进行通信,请求他fork一个子进程出来作为这个即将启动的应用的的进程。
1.创建zygote进程的过程:
AMS 和 PMS 服务都是有systemService服务进程启动的,而systemService服务进程是有zygote服务进程在启动的过程中孕育出来的,
然而我们都知道android是基于Linux内核,而Linux内核系统中,所有的进程但是init进程的子孙进程,也就是说所以的进程都是直接或者
间接的有init进程fork出来的,zygote也不例外,它是在系统启动过程中,有init进行创建的,在系统启动的脚本system/core/rootdir/init.rc
文件中,我们可以看到启动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
Step 1. app_process.main
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/
app_main.cpp文件中,入口函数是main。
在framework/base/cmds/app_process/app_main.cpp的main函数中主要做了如下事情:
int main(int argc, char* const argv[])
{
/* @SPRD: Add log for performance test. @{ */
BOOTINFO("Zygote process start \n");
/* @} */
#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;
BOOTINFO("before zygote \n");
if (zygote) {
/** SPRD: clear dalvik cache when last shutdown abnormal @{ */
// do last shutdown check
BOOTINFO("doLastShutDownCheck \n");
doLastShutDownCheck();
/** @} */
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
BOOTINFO("zygote main class \n");
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;
}
}
在这个main函数中主要就是创建了一个App runtime变量,最后执行的是AppRuntime的成员方法start。
而AppRutime它也继承以AndroidRuntime,当AppRuntime对象被创建时,它会调用其父类AndroidRuntime的构造函数,
而在AndroidRuntime的构造函数中,会将this指针保存在静态全局变量gCurRuntime中,这样当其他的的地方需要使用
AndroidRuntime对象时,就可以通过同一个文件的这个函数来获取这个对象的指针。
回到上面的main方法中,由于我们在init.rc文件中设置了启动参数为 --zygote 和 --start-system-service,因此在main方法里面,最终会执行下面语句。
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
这里的startSystemServer==true,表示启动systemServer组件,而由于AppRuntime类是没有实现自己的start方法,它用的是AndroidRuntime中的start函数。
Step 2. AndroidRuntime.start
个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
void AndroidRuntime::start(const char* className, const char* options)
{
BOOTINFO("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
/* SPRD: add for apct functions @{ */
char buf[2][128] = {'\0'};
nsecs_t time0;
uint32_t time1;
/* @} */
/*
* '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);
/* SPRD: add for apct functions @{ */
if (getApctBootDataSupport())
{
time0 = systemTime();
}
/* @} */
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
/* SPRD: add for apct functions @{ */
if (getApctBootDataSupport())
{
time1 = (uint32_t)ns2ms(systemTime() - time0);
sprintf(buf[0], "BOOTING: start JVM takes: %d ms", time1);
}
/* @} */
onVmCreated(env);
/* SPRD: add for apct functions @{ */
if (getApctBootDataSupport())
{
time0 = systemTime();
}
/* @} */
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/* SPRD: add for apct functions @{ */
if (getApctBootDataSupport())
{
time1 = (uint32_t)ns2ms(systemTime() - time0);
sprintf(buf[1], "BOOTING: Register JNI takes: %d ms", time1);
char *buf_log = (char*)malloc(256);
sprintf(buf_log, "%s\n%s\n", buf[0], buf[1]);
writeInitProcess(buf_log);
free(buf_log);
}
/* @} */
/*
* 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);
BOOTINFO("start class before zygote init \n");
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() != 0)
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 class ZygoteInit {
......
public static void main(String argv[]) {
try {
Log.i(TAG, "zygote init main");
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
/* @SPRD: Add log for performance test. @{ */
boolean performanceTest = Log.isPerformanceTestable();
if (performanceTest) {
Log.startPerfTracking("ZytoteInit" + " preload");
}
/* @} */
preload();
/* @SPRD: Add log for performance test. @{ */
if (performanceTest) {
Log.stopPerfTracking("ZytoteInit" + " preload");
}
Log.i(TAG, "ZytoteInit" + " preload finish");
/* @} */
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
gc();
// Disable tracing so that forked processes do not inherit stale
// tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// 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")) {
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) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
}
这个zygoteInit主要做了三件事情:
首先registerZygoteSocket();函数创建了一个socket接口,用来和AMS通讯。
其次startSystemServer();启动了系统服务组件。
最后runSelectLoop();函数进入了一个无限循环,在前面创建的socket接口上等待ams请求创建新的应用程序进程。
Step 4. ZygoteInit.registerZygoteSocket
public class ZygoteInit {
......
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
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);
}
}
}
}
这个zygote socket 的创建是通过文件描述符创建的,这个文件描述符代表的就是我们前面说的/dev/socket/zygote文件,这个
文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的。
同样有个疑问,你们这个环境变量的值是谁赋予的?我们知道系统启动脚本是system/core/rootdir/init.rc文件,而init.rc文件是
有init进程来解释执行的,而init进程的源代码位于system/core/init/init.c文件中,是由init.c文件中的service_start函数来
解释init.rcwenj
void service_start(struct service *svc, const char *dynamic_args)
{
struct stat s;
pid_t pid;
int needs_console;
int n;
char *scon = NULL;
int rc;
/* 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->time_started = 0;
if((!strncmp(svc->name,"healthd",7))&&(!strcmp(bootmode, "charger"))){
ERROR("stopping '%s'\n", svc->name);
svc->flags |= SVC_DISABLED;
return;
}
/* 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;
}
needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
if (needs_console && (!have_console)) {
ERROR("service '%s' requires console\n", svc->name);
svc->flags |= SVC_DISABLED;
return;
}
if (stat(svc->args[0], &s) != 0) {
ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], 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[0]);
svc->flags |= SVC_DISABLED;
return;
}
if (is_selinux_enabled() > 0) {
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[0]);
rc = getcon(&mycon);
if (rc < 0) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
}
rc = getfilecon(svc->args[0], &fcon);
if (rc < 0) {
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);
freecon(mycon);
freecon(fcon);
if (rc < 0) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
}
}
}
NOTICE("starting '%s'\n", svc->name);
pid = fork();if (pid == 0) {
struct socketinfo *si;
struct svcenvinfo *ei;
char tmp[32];
int fd, sz;
umask(077);
if(!strcmp(svc->name, "zygote")){
BOOTINFO("service_start name is %s \n", svc->name);
}
if (properties_inited()) {
get_property_workspace(&fd, &sz);
sprintf(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);
setsockcreatecon(scon);
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);
if (s >= 0) {
publish_socket(si->name, s);
}
}
freecon(scon);
scon = NULL;
setsockcreatecon(NULL);
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 0
for (n = 0; svc->args[n]; n++) {
INFO("args[%d] = '%s'\n", n, svc->args[n]);
}
for (n = 0; ENV[n]; n++) {
INFO("env[%d] = '%s'\n", n, ENV[n]);
}
#endif
setpgid(0, getpid());
/* as requested, set our gid, supplemental gids, and uid */
if (svc->gid) {
if (setgid(svc->gid) != 0) {
ERROR("setgid failed: %s\n", strerror(errno));
_exit(127);
}
}
if (svc->nr_supp_gids) {
if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) {
ERROR("setgroups failed: %s\n", strerror(errno));
_exit(127);
}
}
if (svc->uid) {
if (setuid(svc->uid) != 0) {
ERROR("setuid failed: %s\n", strerror(errno));
_exit(127);
}
}
if (svc->seclabel) {
if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
_exit(127);
}
}
if(!strcmp(svc->name, "zygote")){
BOOTINFO("service_start end \n");
}
if (!dynamic_args) {
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
}
} else {
char *arg_ptrs[INIT_PARSER_MAXARGS+1];
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] = '\0';
execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
}
_exit(127);
}
freecon(scon);
if (pid < 0) {
ERROR("failed to start '%s'\n", svc->name);
svc->pid = 0;
return;
}
svc->time_started = gettime();
svc->pid = pid;
svc->flags |= SVC_RUNNING;
if (properties_inited())
notify_service_state(svc->name, "running");
}
在init.rc文件中的每个服务命令,都会促使init.c文件中的service_start函数中的fork()为其创建一个新的进程,在新的进程里面,会分析里面的socket选项,
都会通过create_socket(si->name, socket_type,si->perm, si->uid, si->gid);在dev/socket/目录下创建一个文件,在zygote进程中,创建的便是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);
}
当前zygote进程下,上面publish_socket的参数name为zygote,ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_" ,因此这里就把publish_socket得到的“ANDROID_SOCKET_zygote”为key值写入到环境变量中了。
同时ZygoteInit.registerZygoteSocket与init.c文件中的createSocket函数是同一个进程中,所以上面的ZygoteInit.registerZygoteSocket可以直接使用
这个符号描述符来创建一个LocalServiceSocket对象,如果其他的进程也需要打开这个dev/socket/zygote/文件与zygote进行进程间通信,那么需要使用
文件名来连接这个LocalServiceSocket了。
Step 5. Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。
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;
/* SPRD: add for apct functions @{ */
long time0 = 0;
if (APCTOption.self().isApctBootDataSupport())
{
time0 = SystemClock.uptimeMillis();
}
/* @} */
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) {
/* SPRD: add for apct functions @{ */
if (APCTOption.self().isApctBootDataSupport())
{
long time1 = SystemClock.uptimeMillis() - time0;
String str = "BOOTING: fork SystemServer takes: " + time1 + " ms\n";
writeBootDataToProc(str);
}
/* @} */
handleSystemServerProcess(parsedArgs);
}
return true;
}
从这个函数中可以看到,通过Zygote.forkSystemSocket创建了一个新进程来启动systemService组件,返回值pid==0的地方就是新进程要执行的路径,
意思也就是新进程会执行handleSystemServerProcess函数。
Step 6. ZygoteInit.handleSystemServerProcess:
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);
}
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 */
}
由于zygote进程创建的子进程SystemSocket会继承zygote进程在Step 4. ZygoteInit.registerZygoteSocket中创建的socket文件描述符,而这里的子进程又不会用上它,
所以这里调用closeServerSocket();函数来关闭它。
Step 7. RuntimeInit.zygoteInit:
接着继续调用RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);来执行启动systemService组件的操作。
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);
}
private static void applicationInit(int targetSdkVersion, String[] argv)
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;
}
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
这个函数中commonInit();函数中对时区,log日志,http用户代理,网络socket安装进行初始化。
用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进程中的Binder对象就可以方便地进行进程间通信了,这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中,Step 9,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。
applicationInit(targetSdkVersion, argv);中的invokeStaticMain(args.startClass, args.startArgs); 调用上面handleSystemServerProcess(parsedArgs);传进来的com.android.server.SystemServer类的main函数,执行com.android.server.SystemServer类的main函数了。
Step 8. SystemServer.main
这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中: