在init
进程详解的一章中,我们知道init.rc文件中的zygote启动脚本命令是
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
init
程序会创建一个名为service
的结构体,并在 boot
action 执行的时候,调用service_start
方法fork
出一个子进程,并在子进程中执行/system/bin/appress
二进制文件。
zygote
本身是用户空间的一个Native
的应用程序进程,与驱动、内核等均无关系。它最初的名称是app_process
,然后直接调用linux
系统调用pctrl
将进程名称改为了zygote
。
一、 zygote 分析
下面我们来分析app_progress
进程,它对应的文件为frameworks\base\cmds\app_process\App_main.cpp
文件,入口函数为main
int main(int argc, char* const argv[])
{
#ifdef __arm__
/*
* b/7188322 - Temporarily revert to the compat memory layout
* to avoid breaking third party apps.
*
* THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
*
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
* changes the kernel mapping from bottom up to top-down.
* This breaks some programs which improperly embed
* an out of date copy of Android's linker.
*/
char value[PROPERTY_VALUE_MAX];
property_get("ro.kernel.qemu", value, "");
bool is_qemu = (strcmp(value, "1") == 0);
if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
int current = personality(0xFFFFFFFF);
if ((current & ADDR_COMPAT_LAYOUT) == 0) {
personality(current | ADDR_COMPAT_LAYOUT);
setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
execv("/system/bin/app_process", argv);
return -1;
}
}
unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
#endif
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {// 拷贝 剩余的参数到 char* 数组中
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime; //创建AppRuntime对象
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
/*
将 -Xzygote /system/bin --zygote --start-system-server之前的VM 参数
用JavaVMOption 结构体初始化,添加到 mOptions 集合中
*/
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;
//处理剩余的 "-Xzygote /system/bin --zygote --start-system-server"启动参数
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote"; // 配置该选项后,表明将app_progress的进程名改为zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; //表明启动 system_server
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12; // 配置该选项后,表明将app_progress的进程名改为其它名字
} else {
className = arg;
break;
}
}
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);//将app_progress进程名改为niceName,默认情况下为zygote
}
runtime.mParentDir = parentDir;
if (zygote) {
//调用runtime的start方法,该方法的第二个参数为start-system-server
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
主要功能在AppRuntime
中实现
1.1AppRuntime分析
AppRuntime 类的声名和实现均在App_main.cpp
中,它是从Android_Runtime
中派生出来的。重载了其中的onStart
方法:
/*
* 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 char* options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
/*
* '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)));
}
//设置环境变量"ANDROID_ROOT"的值为"/system"
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;
//启动虚拟机,得到当前虚拟机对象JavaVM为全局静态变量
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.//注册定义好的jni函数
*/
if (startReg(env) < 0) {
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.
*/
/**
为了调用"com.android.internal.os.ZygoteInit"类中的main(String[])函数。我们需要先创建
一个String[] 对象数组,用于存放"com.android.internal.os.ZygoteInit",和后面的参数
**/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
//创建一个有两个String 对象数组,即Java代码: String strArray[]=new String[2];
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
//设置数组第一个元素为"com.android.internal.os.ZygoteInit"
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
//设置数组第二个元素为"start-system-server"
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.
*/
//将"com.android.internal.os.ZygoteInit"换成"com/android/internal/os/ZygoteInit",符合jni调用规范
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit类的static main 方法jmentod ID
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 {
//调用ZygoteInit类的main静态方法,Zygote进入了Java世界!
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");
}
通过上面的分析,我们知道了AndroidRuntime::start主要做的三件事:
1.调用startVm创建虚拟机对象。
2.调用startReg注册好定义的JNI函数。
3.调用找到”com.android.internal.os.ZygoteInit”类的static main 函数进入Java世界
### 1.调用startVM创建Java虚拟机
在AndroidRuntime::startVm
方法中,初始化了创建虚拟机的参数,然后创建虚拟机。
/*
* Start the Dalvik Virtual Machine.
*
* Various arguments, most determined by system properties, are passed in.
* The "mOptions" vector is updated.
*
* Returns 0 on success.
*/
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
int result = -1;
JavaVMInitArgs initArgs;
JavaVMOption opt;
.....
/*
*
这个函数的前部分都是根据系统的属性配置文件创建JavaVMOption结构体,添加
到mOptions集合中,用来设置虚拟机参数。
*/
/*
设置JNI check选项,指的是在 Native层调用JNI函数时,系统做的一些检查工作
比如调用NewUTFString时,系统会检查传入的字符串是不是符合UTF-8的需求。
*/
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
...
/*
* The default starting and maximum size of the heap. Larger
* values should be specified in a product property override.
*/
strcpy(heapstartsizeOptsBuf, "-Xms");
property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");
opt.optionString = heapstartsizeOptsBuf;
mOptions.add(opt);
/*
设置虚拟机的heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。
heapsize 不能设置得过小,否则在操作大尺寸的图片时无法分配所需的内存。
*/
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
/*
* We don't have /tmp on the device, but we often have an SD card. Apps
* shouldn't use this, but some test suites might want to exercise it.
*/
opt.optionString = "-Djava.io.tmpdir=/sdcard";
mOptions.add(opt);
initArgs.version = JNI_VERSION_1_4;
initArgs.options = mOptions.editArray();
initArgs.nOptions = mOptions.size();
initArgs.ignoreUnrecognized = JNI_FALSE;
/*
* Initialize the VM.
*
* The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
* If this call succeeds, the VM is ready, and we can start issuing
* JNI calls.
*/
/*
创建并初始化虚拟机,JavaVM对象是每个进程只有一个。JNIEnv 是每个线程一个。
*/
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
2.注册JNI函数
Java世界用到的一些类的方法是用native方式实现的需要系统提前注册,下面查看startReg函数
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
/*
*设置 Thread类的线程创建函数为javaCreateThreadEtc
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
//注册JNI函数。gREgJNI是一个全局数组,里面存放了要注册的Java类对应的注册函数的函数指针
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
我们来查看register_jni_procs
,代码如下所示:
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
//调用数组中才mProc元素,该元素是一个函数指针,int (*mProc)(JNIEnv *),指向类对应的注册函数
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
gRegJNI全局数组
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
...
}
register_android_debug_JNITest对应的注册函数:
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "part1", "(IDLjava/lang/String;[I)I",
(void*) android_debug_JNITest_part1 },
{ "part3", "(Ljava/lang/String;)I",
(void*) android_debug_JNITest_part3 },
};
int register_android_debug_JNITest(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "android/debug/JNITest",
gMethods, NELEM(gMethods));
}
2.Java世界分析
通过前面的分析我们知道,Java世界的入口函数为com.android.internal.os.ZygoteInit
类的main函数。我们来查看这个main函数:
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
//1.注册ZygoteSocket用的Socket
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//2.预加载类、资源、OpenGL
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
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();//3.启动system_server进程
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
//调用函数runSelectLoop进入一个无限循环
//4.在前面创建的 socket接口中等待ActivityManagerService请求,以创建新的应用程序进程
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
//5.反射调用执行函数
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
在ZygoteInit类的main函数中,我们知道ZygoteInit类主要做了5件事情:
1.注册ZygoteSocket用的Socket
2.预加载类、资源、OpenGL
3.启动system_server进程
4.在前面创建的 socket接口中等待ActivityManagerService请求,以创建新的应用程序进程
5.反射调用执行函数
1.建立IPC通信服务断-registerZygoteSocket
zygote及系统中其他层序的通信没有使用Binder,而是采用了基于AF_UNIX类型的Socket。registerZygoteSocket 函数就是使用的该Socket
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
//从环境变量中获取Zygote Socket文件描述符,环境变量为ANDROID_SOCKET_zygote=fd
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 {
//根据文件描述符创建服务端Socket,并监听
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
LocalServerSocket 的构造方法
/**
58 * Create a LocalServerSocket from a file descriptor that's already
59 * been created and bound. listen() will be called immediately on it.
60 * Used for cases where file descriptors are passed in via environment
61 * variables
62 *
63 * @param fd bound file descriptor
64 * @throws IOException
65 */
66 public LocalServerSocket(FileDescriptor fd) throws IOException
67 {
68 impl = new LocalSocketImpl(fd);
69 impl.listen(LISTEN_BACKLOG);
70 localAddress = impl.getSockAddress();
71 }
2.预加载类和资源和OpenGL
然后调用preload函数加载一些预加载操作:
static void preload() {
preloadClasses();
preloadResources();
preloadOpenGL();
}
preloadClasses()函数会预加载类:
/**
* Performs Zygote process initialization. Loads and initializes
* commonly used classes.
*
* Most classes only cause a few hundred bytes to be allocated, but
* a few will allocate a dozen Kbytes (in one case, 500+K).
*/
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
//预加载类的信息存储在PRELOADED_CLASSES变量中,它的值为"preloaded-classes"
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(
PRELOADED_CLASSES);
......
try {
BufferedReader br
= new BufferedReader(new InputStreamReader(is), 256);
//读取文件的每一行,忽略#开头的注释行。
int count = 0;
String line;
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
if (false) {
Log.v(TAG, "Preloading " + line + "...");
}
//通过Java反射来加载类,line中存储的是预加载的类名
Class.forName(line);
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (false) {
Log.v(TAG,
" GC at " + Debug.getGlobalAllocSize());
}
System.gc();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
}
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
}
Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
IoUtils.closeQuietly(is);
// Restore default.
runtime.setTargetHeapUtilization(defaultUtilization);
// Fill in dex caches with classes, fields, and methods brought in by preloading.
runtime.preloadDexCaches();
Debug.stopAllocCounting();
// Bring back root. We'll need it later.
setEffectiveUser(ROOT_UID);
setEffectiveGroup(ROOT_GID);
}
}
}
rameworks\base\preloaded-classes
文件中保存了需要预先加载的类,整个加载过程十分耗时,这是android启动缓慢的原因之一。
PreloadResource和preloadClass类似,它主要是加载framework-res.apk中的资源。在UI编程中常使用的com.android.R.XXX 资源是系统默认的资源,它们就是由zygote加载的
3.启动system_server
startSystemServer函数会创建Java世界中系统Service所驻留的进程system_server,该进程是framework的核心。如果给进程结束,Zygote进程也会结束。
/**
* Prepare the arguments and fork for the system server process.
*/
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
);
//硬编码设置system_server进程参数
/* 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",//system_server进程进程名
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//将参数转化成Arguments对象
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//fork一个子进程,这个进程就是system_server进程
/* 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) {
//system_server进程的工作
handleSystemServerProcess(parsedArgs);
}
//zygote进程返回true
return true;
}
zygote进行了一次无性繁殖,分裂出system_server.
- 循环接收等待请求-runSelectLoopMode
待zygote
从startSystemServer运回后,将进入第四个关键函数:runSelectLoopMode。前面在第一个关键点registerZygoteSocket中注册的一个用于IPC的Socket,它的runSelectLoopMode中将体现出来 :
/**
* 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() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
/*
selectReadable 内部调用select,使用多路复用I/O模型。
当有客户端连接或有数据时,则selectReadable就会返回。
当有新的连接时,返回ServerSocket的数组下标0
当有Socket数据可读取时,返回 ZygoteConnectionSocket的数组下标
*/
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
//有一个客户端连接上。客户端在Zygote的代表ZygoteConnection,它包装了LocalSocket对象
ZygoteConnection newPeer = acceptCommandPeer();
//将返回的ZygoteConnection对应添加到集合中。
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//客户端有数组传送时,找到对应的ZygoteConnection,调用runOnce()方法进行处理
done = peers.get(index).runOnce();
//处理完成后从集合中移除相应的ZygoteConnection;
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
runSelectLoop比较简单,就是
1.处理客户连接和客户请求。其中客户在zygote中用ZygoteConnection对象来表示。
2客户的请求由ZygoteConnection的runOnce来处理。
2.3 关于Zygote的总结
整个Zygote创建Java世界的步骤:
1.调用startVm创建虚拟机对象。
2.调用startReg注册好定义的JNI函数。
3.调用找到”com.android.internal.os.ZygoteInit”类的static main 函数进入Java世界
4.注册ZygoteSocket用的Socket
5.预加载类、资源、OpenGL
6.启动system_server进程
7.在前面创建的 socket接口中等待ActivityManagerService请求,以创建新的应用程序进程
二、SystemServer 分析
2.1 SystemServer的创建
SystemServer的进程名实际上叫做system_server
,这里我们可将其简称为SS:
/**
* Prepare the arguments and fork for the system server process.
*/
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
);
//硬编码设置system_server进程参数
/* 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",//system_server进程进程名
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//将参数转化成Arguments对象
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//fork一个子进程,这个进程就是system_server进程
/* 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) {
//system_server进程的工作
handleSystemServerProcess(parsedArgs);
}
//zygote进程返回true
return true;
}
从上面的代码我们可以看出,SS是由Zygote通过Zygote.forkSystemServer
函数fork诞生出来,它是一个native函数,实现在dalvik_system_Zygote.c
中,如下
/*
* native public static int nativeForkSystemServer(int uid, int gid,
* int[] gids, int debugFlags, int[][] rlimits,
* long permittedCapabilities, long effectiveCapabilities);
*/
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
//根据参数,fork子进程
pid = forkAndSpecializeCommon(args, true);
/* The zygote process checks whether the child process has died or not. */
if (pid > 0) {
int status;
ALOGI("System server process %d has been created", pid);
//保存system_server进程的进程ID
gDvm.systemServerPid = pid;
/* There is a slight window that the system server process has crashed
* but it went unnoticed because we haven't published its pid yet. So
* we recheck here just to make sure that all is well.
*/
//退出前检查刚才创建的system_server子进程是否退出
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
//如果system_server子进程退出,则干掉zygote进程,重启zygote进程。
kill(getpid(), SIGKILL);
}
}
RETURN_INT(pid);
}
forkAndSpecializeCommon
函数:
/*
* Utility routine to fork zygote and specialize the child process.
*/
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
pid_t pid;
//设置进程信息
uid_t uid = (uid_t) args[0];
gid_t gid = (gid_t) args[1];
ArrayObject* gids = (ArrayObject *)args[2];
u4 debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
u4 mountMode = MOUNT_EXTERNAL_NONE;
int64_t permittedCapabilities, effectiveCapabilities;
char *seInfo = NULL;
char *niceName = NULL;
....
//设置信号处理函数
setSignalHandler();
dvmDumpLoaderStats("zygote");
//fork子进程
pid = fork();
if (pid == 0) {
//对子进程进行一些处理工作,如设置进程名,设置各种ID等
int err;
/* The child process */
...
} else if (pid > 0) {
/* the parent process */
free(seInfo);
free(niceName);
}
return pid;
}
查看setSignalHandler
函数,它由Zygote
在fork
子进程前调用
/*
* configure sigchld handler for the zygote process
* This is configured very late, because earlier in the dalvik lifecycle
* we can fork() and exec() for the verifier/optimizer, and we
* want to waitpid() for those rather than have them be harvested immediately.
*
* This ends up being called repeatedly before each fork(), but there's
* no real harm in that.
*/
static void setSignalHandler()
{
int err;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigchldHandler;
err = sigaction (SIGCHLD, &sa, NULL);
if (err < 0) {
ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
}
}
/*
* This signal handler is for zygote mode, since the zygote
* must reap its children
*/
static void sigchldHandler(int s)
{
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
/* Log process-death status that we care about. In general it is not
safe to call ALOG(...) from a signal handler because of possible
reentrancy. However, we know a priori that the current implementation
of ALOG() is safe to call from a SIGCHLD handler in the zygote process.
If the ALOG() implementation changes its locking strategy or its use
of syscalls within the lazy-init critical section, its use here may
become unsafe. */
/*
* If the just-crashed process is the system_server, bring down zygote
* so that it is restarted by init and system server will be restarted
* from there.
*/
//如果死去的进程是SS,则Zygote把自己也干掉了,
if (pid == gDvm.systemServerPid) {
ALOG(LOG_INFO, ZYGOTE_LOG_TAG,
"Exit zygote because system server (%d) has terminated",
(int) pid);
kill(getpid(), SIGKILL);
}
}
if (pid < 0) {
ALOG(LOG_WARN, ZYGOTE_LOG_TAG,
"Zygote SIGCHLD error in waitpid: %s",strerror(errno));
}
}
SystemServer与Zygote进程生死与共。
2.2 SystemServer的重要使命
SystemServer
,创建以后它的主要任务什么?
...
/* For child process */
if (pid == 0) {
//system_server进程的工作
handleSystemServerProcess(parsedArgs);
}
...
然后我们查看 handleSystemServerProcess()
方法:
ZygoteInit.java
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
//关闭从Zygote那里继承下来的Socket.
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) {
//设置当前Systemserver进程名为system_server
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.
*/
//调用ZygoteInit函数
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
/* should never reach here */
}
在上述代码中,调用函数closeServerSocket
后,
然后调用RuntimeInit.zygoteInit方法进行初始化
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> [--] <start class name> <args>
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
//做常规初始化,设置System进程的时区和键盘布局。
commonInit();
//调用函数nativeZygoteInit启动一个Binder线程池。
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);
}
applicationInit方法
# RuntimeInit.java
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
...
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
invokeStaticMain()方法
RuntimeInit.java
/**
* 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()
*/
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
//className为"com.android.server.SystemServer"
Class<?> cl;
try {
cl = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
//找到com.android.server.SystemServer类的main函数。
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
//抛出异常,在ZygoteInit.main()方法中被捕获,然后调用run方法执行main函数
//这样做的目的是清除设置进程信息中的堆栈
throw new ZygoteInit.MethodAndArgsCaller( , argv);
}
抛出异常,在ZygoteInit.main()方法中被捕获,然后调用run方法执行main函数这样做的目的是清除设置进程信息中
Zygote.java
try {
...
startSystemServer();//3.启动system_server进程
...
//调用函数runSelectLoop进入一个无限循环
//4.在前面创建的 socket接口中等待ActivityManagerService请求,以创建新的应用程序进程
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
//5.反射调用执行函数
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
2.3 SystemServer的main函数详解
ZygoteInit分裂产生的SystemServer,主要是为了调用frameworks\base\services\java\com\android\server\SystemServer.java
类的main函数
#frameworks\base\services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
/*
* 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",
VMRuntime.getRuntime().vmLibrary());
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
// 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.
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
//SystemServer性能分析,每小时统计一次
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
//和Dalvik虚拟机相关的设置。主要是内存使用方面的控制
// Mmmmmm... more memory!
dalvik.system.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);
Environment.setUserRequired(true);
//加载动态库libandroid_server.so库,调用nativeInit函数进行初始化。
System.loadLibrary("android_servers");
Slog.i(TAG, "Entered the Android system server!");
// Initialize native services.
//初始化native服务,本版本中只是启动了传感器服务
nativeInit();
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
//ServerThread过去用在独立才线程中,现在用在主线程中
ServerThread thr = new Serve rThread();
//在initAndLoop方法中创建各种服务
thr.initAndLoop();
}
在main方法中加载android_servers.so库,启动native服务
#frameworks\base\services\jni\com_android_server_SystemServer.cpp
static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
//启动传感器服务
SensorService::instantiate();
}
}
然后创建ServerThread对象,调用initAndLoop方法在主线程中创建各种服务对象
#frameworks\base\services\java\com\android\server\SystemServer.java
public void initAndLoop() {
...
//在当前线程中设置Looper对象,Looper内部有消息队列
Looper.prepareMainLooper();
//在当前线程中设置Looper对象,Looper内部有消息队列
Looper.prepareMainLooper();
......
//创建ActivityManagerService对象
context = ActivityManagerService.main(factoryTest);
......
//启动PackageManagerService服务
pm = PackageManagerService.main(context, installer,
factoryTest != SystemServer.FACTORY_TEST_OFF,
onlyCore);
......
//将ActivityManagerService服务对象添加到ServiceManager对中
ActivityManagerService.setSystemProcess();
......
Looper.loop();
三、应用程序创建进程详解(zygote的分裂)
在启动Android应用程序过程中,除了可以获得虚拟机实例外,还可以获得一个消息循环和Binder线程池。这样
在应用程序中运行的组件,可以使用系统的信息处理机制和Binder通信机制实现自己的业务逻辑。
zygote 分裂出嫡长子system_server后,通过runSelectLoopMode等待并处理来自客户信息,
这个信息由ActivityManagerService发送
3.1 ActivityManagerService发送请求
ActivityManagerService也是由SystemServer创建。当我们通过startActivity来启动一个新的Activity,而这个Activity
附属于一个还未启动的进程,这个进程由ActivityManagerService中的startProcessLocked创建。
# frameworks\base\services\java\com\android\server\am\ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
updateCpuStats();
//获取创建应用程序进程的用户ID和用户组ID
try {
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
//检查是否有获取外部存储的权限,有的话挂载
if (Environment.isExternalStorageEmulated()) {
if (pm.checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
/*
* Add shared application GID so applications can share some
* resources like shared libraries
*/
//添加共享组应用ID以便共享资源
if (permGids == null) {
gids = new int[1];
} else {
gids = new int[permGids.length + 1];
System.arraycopy(permGids, 0, gids, 1, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
}
if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
&& mTopComponent != null
&& app.processName.equals(mTopComponent.getPackageName())) {
uid = 0;
}
if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
&& (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
uid = 0;
}
}
int debugFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
// Also turn on CheckJNI for debuggable apps. It's quite
// awkward to turn on otherwise.
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
Zygote.systemInSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
//调用函数start创建应用程序进程,调用成功后返回的结果中有进程ID,调用失败后会抛出异常。Process类由android提供,非jdk
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null);
BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
synchronized (bs) {
if (bs.isOnBattery()) {
bs.getProcessStatsLocked(app.uid, app.processName).incStartsLocked();
}
}
EventLog.writeEvent(EventLogTags.AM_PROC_START,
UserHandle.getUserId(uid), startResult.pid, uid,
app.processName, hostingType,
hostingNameStr != null ? hostingNameStr : "");
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(app.processName);
buf.append(" for ");
buf.append(hostingType);
if (hostingNameStr != null) {
buf.append(" ");
buf.append(hostingNameStr);
}
buf.append(": pid=");
buf.append(startResult.pid);
buf.append(" uid=");
buf.append(uid);
buf.append(" gids={");
if (gids != null) {
for (int gi=0; gi<gids.length; gi++) {
if (gi != 0) buf.append(", ");
buf.append(gids[gi]);
}
}
buf.append("}");
Slog.i(TAG, buf.toString());
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
} catch (RuntimeException e) {
// XXX do better error recovery.
app.setPid(0);
Slog.e(TAG, "Failure starting process " + app.processName, e);
}
}
在该方法中,调用了Android中Process类的start方法,并传递了android.app.ActivityThread字符串参数
#frameworks\base\core\java\android\Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String[] zygoteArgs) {
try {
//调用函数startViaZygote让Zygote进程创建一个应用程序进程,processClass的值为"android.app.ActivityThread"
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
在该方法中,调用了startViaZygote
方法,该方法是将要创建的应用程序进程的启动参数,封装到名为argsForZygote
列表中,
并调用zygoteSendArgsAndGetPid
函数请求进程Zygote进程创建应用程序。
#frameworks\base\core\java\android\Process.java
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
//将参数封装到argsForZygote列表中
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-init, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-init");//这个参数很重要
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
argsForZygote.add("--mount-external-multiuser");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
argsForZygote.add("--mount-external-multiuser-all");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");
// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//请求进程Zygote创建应用程序
return zygoteSendArgsAndGetResult(argsForZygote);
}
}
在zygoteSendArgsAndGetPid
函数中,首先调用函数openZygoteSocketIfNeeded
创建一个连接到Zygote进程的本地对象LocalSocket
,然后将
封装好的参数通过socket发送到zygote进程中
#frameworks\base\core\java\android\Process.java
private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
//调用函数openZygoteSocketIfNeeded创建一个连接到Zygote进程的本地对象LocalSocket.
openZygoteSocketIfNeeded();
try {
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
/**
*将要创建的应用程序进程启动参数列表写入到本地对象LocalSocket中
*Zygote进程接收到数据之后会创建一个新的应用程序进程,将创建的进程Pid
*返回给ActivityManagerService
*/
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
//将返回进程ID保存在ProcessStartResult中
result.pid = sZygoteInputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = sZygoteInputStream.readBoolean();
return result;
} catch (IOException ex) {
try {
if (sZygoteSocket != null) {
sZygoteSocket.close();
}
} catch (IOException ex2) {
// we're going to fail anyway
Log.e(LOG_TAG,"I/O exception on routine close", ex2);
}
sZygoteSocket = null;
throw new ZygoteStartFailedEx(ex);
}
}
openZygoteSocketIfNeeded函数创建一个连接到Zygote进程的本地对象LocalSocket
#frameworks\base\core\java\android\Process.java
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
int retryCount;
if (sPreviousZygoteOpenFailed) {
/*
* If we've failed before, expect that we'll fail again and
* don't pause for retries.
*/
retryCount = 0;
} else {
retryCount = 10;
}
/*
* See bug #811181: Sometimes runtime can make it up before zygote.
* Really, we'd like to do something better to avoid this condition,
* but for now just wait a bit...
*/
for (int retry = 0
; (sZygoteSocket == null) && (retry < (retryCount + 1))
; retry++ ) {
if (retry > 0) {
try {
Log.i("Zygote", "Zygote not up yet, sleeping...");
Thread.sleep(ZYGOTE_RETRY_MILLIS);
} catch (InterruptedException ex) {
// should never happen
}
}
try {
//创建一个名为sZygoteSocket的LocalSocket的对象
sZygoteSocket = new LocalSocket();
//将sZygoteSocket对象名为zygote的Socket地址进行连接
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
//将sZygoteSocket对象的输入流保存在sZygoteInputStream中
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
//将sZygoteSocket对象的输出流保存在sZygoteWriter
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
sZygoteSocket.getOutputStream()),
256);
Log.i("Zygote", "Process: zygote socket opened");
sPreviousZygoteOpenFailed = false;
break;
} catch (IOException ex) {
if (sZygoteSocket != null) {
try {
sZygoteSocket.close();
} catch (IOException ex2) {
Log.e(LOG_TAG,"I/O exception on close after exception",
ex2);
}
}
sZygoteSocket = null;
}
}
if (sZygoteSocket == null) {
sPreviousZygoteOpenFailed = true;
throw new ZygoteStartFailedEx("connect failed");
}
}
3.2 Zygote等待请求创建应用程序进程
在第一节中我们知道,Zygote
在runSelectLoopMode()
方法中循环等待Socket连接
# \frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
private static void runSelectLoop() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
/*
selectReadable 内部调用select,使用多路复用I/O模型。
当有客户端连接或有数据时,则selectReadable就会返回。
当有新的连接时,返回ServerSocket的数组下标0
当有Socket数据可读取时,返回 ZygoteConnectionSocket的数组下标
*/
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
//有一个客户端连接上。客户端在Zygote的代表ZygoteConnection,它包装了LocalSocket对象
ZygoteConnection newPeer = acceptCommandPeer();
//将返回的ZygoteConnection对应添加到集合中。
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//客户端有数组传送时,找到对应的ZygoteConnection,调用runOnce()方法进行处理
done = peers.get(index).runOnce();
//处理完成后从集合中移除相应的ZygoteConnection;
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
每当有请求数据发来时,Zygote就会调用ZygoteConnection的runOnce函数
# frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
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) {
// 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);
applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Libcore.os.pipe();
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
//调用函数forkAndSpecialize创建应用程序进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName);
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} 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) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//子进程处理,这个子进程是我们要创建的对应Activity子进程
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// 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);
}
}
在上述代码中,通过函数readArgumentList获得启动进程的参数,并通过forkAndSpecialize创建这个要启动应用程序的进程.
readArgumentList方法
# frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
private String[] readArgumentList()
throws IOException {
/**
* See android.os.Process.zygoteSendArgsAndGetPid()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure.
*/
int argc;
try {
String s = mSocketReader.readLine();
if (s == null) {
// EOF reached.
return null;
}
argc = Integer.parseInt(s);
} catch (NumberFormatException ex) {
Log.e(TAG, "invalid Zygote wire format: non-int at argc");
throw new IOException("invalid wire format");
}
// See bug 1092107: large argc can be used for a DOS attack
if (argc > MAX_ZYGOTE_ARGC) {
throw new IOException("max arg count exceeded");
}
String[] result = new String[argc];
for (int i = 0; i < argc; i++) {
result[i] = mSocketReader.readLine();
if (result[i] == null) {
// We got an unexpected EOF.
throw new IOException("truncated request");
}
}
return result;
}
如果是子进程,会调用handleChildProc
方法来启动这个子进程:
# frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
//关闭用于接收消息的ClientScoket
closeSocket();
//关闭继承继承下来的ServerSocket
ZygoteInit.closeServerSocket();
if (descriptors != null) {
try {
ZygoteInit.reopenStdio(descriptors[0],
descriptors[1], descriptors[2]);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (IOException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
//设置当前进程名
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
//由于之前设置了runtimeInit函数,因此会进入该分支
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
//没有设置invokeWith参数,会进入到下面的分支中
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
} else {
String className;
try {
className = parsedArgs.remainingArgs[0];
} catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument", null);
return;
}
String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
System.arraycopy(parsedArgs.remainingArgs, 1,
mainArgs, 0, mainArgs.length);
if (parsedArgs.invokeWith != null) {
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
} else {
ClassLoader cloader;
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
} else {
cloader = ClassLoader.getSystemClassLoader();
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
}
}
接着会调用RuntimeInit.zygoteInit方法进一步初始化该进程
# frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
//做常规初始化,设置System进程的时区和键盘布局。
commonInit();
//调用函数nativeZygoteInit启动一个Binder线程池。
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);
}
在applicationInit方法中,会调用 invokeStaticMain方法启动android.app.ActivityThread类的main函数
# frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
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;
}
//调用startClass,也就是com.android.server.SystemServer函数
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
通过分析我们知道android.app.ActivityThread类实际上是Android中apk程序所对应的进程,它的main函数也就是
apk程序的main函数。
系统运行的apk程序,其父进程都是zygote进程 。