在Android系统中,如果用ps来查看进程列表的话,会发现有一个进程是zygote,它的父进程是init,而且,它是所有应用的父进程;还有一个进程是system_server,它的父进程是zygote。
事实上, zygote正是我们所说的JVM。而system_server进程又该如何理解呢?其实,它是整个Android Framework所在的进程。这样,我们所说的android系统最核心的组成部分就呈现给大家了(当然,这里先将kernel和应用除外),即jvm+framework。本文描述了整个jvm 和 system_server的初始化过程,这篇文章是在本博另外一篇文章"android初始化流程”的基础上继续探讨的。
一. zygote进程是通过app_process的方式启动的,而且是在init.rc中指定的,具体如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
app_process是一个用可执行程序,代码位于: frameworks\base\cmds\app_process\目录下。
二. system_server既然是zygote的子进程,理所当然,是由zygote来初始化的。
1. 通过app_process启动zygote:
(1)app_main.cpp中的main函数:
int main(int argc, const char* const argv[])
{
// 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 *arg;
const char *argv0;
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);
// Next arg is parent directory
if (i < argc) {
runtime.mParentDir = argv[i++];
}
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
// Remainder of args get passed to startup class main()
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
LOGV("App process is starting with pid=%d, class=%s.\n",
getpid(), runtime.getClassName());
runtime.start();
}
} else {
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
return 10;
}
}
(2)AndroidRuntime.cpp中的start(位于frameworks\base\core\jni\AndroidRuntime.cpp):
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
......
preloadClasses();
//cacheRegisterMaps();
preloadResources();
......
/*
* 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.
*/
if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we only have one argument, the class name. Create an
* array to hold it.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
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);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
LOGE("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
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
free(stackTraceFile);
}
说明:
(1) LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
这个log信息应该不陌生了吧。
(2) preloadClasses(); 和preloadResources();, 顾名思义,它加载了许多class和resources,libmedia_jni.so 和libwebcore就是在这里加载的(在本文最后面,会给出相关的log信息,里面显示了加载了哪些库,一定要看喔:))。
(3)
(4) GetStaticMethodID和 CallStaticVoidMethod就会调用 传入的class的对应的方法。
这里,class是ZygoteInit,方法是main, 而ZygoteInit位于ZygoteInit.java中,注意,从这里开始,
首次以java定义的类来调用,因为在这之前,jvm也初始化好了,需要jniEnv的参数也设置好了。
于是,就会执行到下面的ZygoteInit.java的main函数中。
2. ZygoteInit.java
代码:
位于frameworks\base\core\java\com\android\internal\os目录下。
在它的main函数中,最主要的就是:
startSystemServer(); 这个函数也位于ZygoteInit.java中,代码如下:
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* 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,3001,3002,3003",
"--capabilities=121715744,121715744",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
/*
* Enable debugging of the system process if *either* the command line flags
* indicate it should be debuggable or the ro.debuggable system property
* is set to "1"
*/
int debugFlags = parsedArgs.debugFlags;
if ("1".equals(SystemProperties.get("ro.debuggable")))
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
说明:
(1) 设置进程的参数是system_server, ;
对应的类是com.android.server.SystemServer。
(2) Zygote.forkSystemServer真正地fork一个进程,参数前面已经设置好了,所以,这个fork出来的进程就是system_server,而这个进程恰恰是zygote的子进程(用ps可以看到)。
(3) Zygote.forkSystemServer相关:
它调用了forkAndSpecialize(dalvik\libcore\dalvik\src\main\java\dalvik\system\zytote.java), 而后者又通过jni的方式调用到
Dalvik_dalvik_system_Zygote_forkSystemServer(dalvik\vm\native\dalvik_system_Zygote.c),继而调用到forkAndSpecializeCommon,在这个函数中,通过 fork()函数来真正创建一个进程。这里,如果看log的话,有打印语句:LOGE("System server process %d has died. Restarting Zygote!", pid);, 而这个log在本文最后给出的log中也是有体现的。
所以,最终,还是回到了下层的c或者cpp代码中; 而jvm只不过是对fork()进行了封装,当然,这只是它的一个必不可少的功能之一而已。
3. system_server:
system_server上面也提到了,是一个进程,事实上,它是整个Framework的主进程,在这个进程中,会创建并启动一个thread,而这个线程是整个framework的主线程,在这个线程中,这里声明并初始化了所有的framework组件。代码位于:
systemserver.java(位于frameworks\base\services\java\com\android\server)
至此, 整个Android os 可以认为是启动完毕。
4. log,是在开机过程中抓取的,当然,用的是logcat:
09-07 06:21:52.288: DEBUG/AndroidRuntime(541): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
09-07 06:21:52.288: DEBUG/AndroidRuntime(541): CheckJNI is ON
......
09-07 06:21:52.937: INFO/(542): ServiceManager: 0xac38
09-07 06:21:52.957: INFO/AudioFlinger(542): AudioFlinger's thread ready to run for output 0
09-07 06:21:52.957: INFO/CameraService(542): CameraService started: pid=542
09-07 06:21:52.978: DEBUG/AndroidRuntime(541): --- registering native functions ---
09-07 06:21:53.308: INFO/Zygote(541): Preloading classes...
09-07 06:21:53.318: DEBUG/dalvikvm(541): GC freed 764 objects / 42216 bytes in 11ms
09-07 06:21:53.517: DEBUG/dalvikvm(541): GC freed 278 objects / 17160 bytes in 4ms
09-07 06:21:53.898: DEBUG/dalvikvm(541): GC freed 208 objects / 12696 bytes in 6ms
09-07 06:21:53.988: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
09-07 06:21:54.148: DEBUG/dalvikvm(541): Added shared lib /system/lib/libmedia_jni.so 0x0
09-07 06:21:54.148: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
09-07 06:21:54.158: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
09-07 06:21:54.158: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
09-07 06:21:54.168: DEBUG/dalvikvm(541): GC freed 462 objects / 29144 bytes in 8ms
......
09-07 06:21:58.748: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libwebcore.so 0x0
09-07 06:21:58.828: DEBUG/dalvikvm(541): Added shared lib /system/lib/libwebcore.so 0x0
......
09-07 06:22:02.258: INFO/Zygote(541): ...preloaded 1166 classes in 8951ms.
09-07 06:22:02.337: DEBUG/dalvikvm(541): GC freed 313 objects / 19952 bytes in 67ms
09-07 06:22:02.337: INFO/Zygote(541): Preloading resources...
......
09-07 06:22:03.509: INFO/dalvikvm(541): Splitting out new zygote heap
09-07 06:22:03.569: INFO/dalvikvm(541): System server process 570 has been created
09-07 06:22:03.569: INFO/Zygote(541): Accepting command socket connections
09-07 06:22:03.638: INFO/jdwp(570): received file descriptor 10 from ADB
09-07 06:22:03.797: DEBUG/dalvikvm(570): Trying to load lib /system/lib/libandroid_servers.so 0x0
09-07 06:22:04.008: DEBUG/dalvikvm(570): Added shared lib /system/lib/libandroid_servers.so 0x0
09-07 06:22:04.027: INFO/sysproc(570): Entered system_init()
09-07 06:22:04.051: INFO/sysproc(570): ServiceManager: 0x16c900
09-07 06:22:04.051: INFO/SurfaceFlinger(570): SurfaceFlinger is starting
09-07 06:22:04.058: INFO/SurfaceFlinger(570): SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
09-07 06:22:04.079: ERROR/MemoryHeapBase(570): error opening /dev/pmem: No such file or directory
09-07 06:22:04.087: ERROR/SurfaceFlinger(570): Couldn't open /sys/power/wait_for_fb_sleep or /sys/power/wait_for_fb_wake
09-07 06:22:04.117: ERROR/GLLogger(570): couldn't load <libhgl.so> library (Cannot find library)
09-07 06:22:04.127: INFO/SurfaceFlinger(570): EGL informations:
09-07 06:22:04.127: INFO/SurfaceFlinger(570): # of configs : 6
09-07 06:22:04.127: INFO/SurfaceFlinger(570): vendor : Android
09-07 06:22:04.127: INFO/SurfaceFlinger(570): version : 1.31 Android META-EGL
09-07 06:22:04.127: INFO/SurfaceFlinger(570): extensions:
09-07 06:22:04.127: INFO/SurfaceFlinger(570): Client API: OpenGL ES
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): using (fd=22)
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): id =
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): xres = 320 px
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): yres = 480 px
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): xres_virtual = 320 px
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): yres_virtual = 960 px
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): bpp = 16
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): r = 11:5
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): g = 5:6
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): b = 0:5
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): width = 49 mm (165.877548 dpi)
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): height = 74 mm (164.756760 dpi)
09-07 06:22:04.127: INFO/EGLDisplaySurface(570): refresh rate = 60.00 Hz
09-07 06:22:04.138: WARN/HAL(570): load: module=/system/lib/hw/copybit.goldfish.so error=Cannot find library
09-07 06:22:04.138: WARN/HAL(570): load: module=/system/lib/hw/copybit.default.so error=Cannot find library
09-07 06:22:04.138: WARN/SurfaceFlinger(570): ro.sf.lcd_density not defined, using 160 dpi by default.
09-07 06:22:04.148: INFO/SurfaceFlinger(570): OpenGL informations:
09-07 06:22:04.148: INFO/SurfaceFlinger(570): vendor : Android
09-07 06:22:04.148: INFO/SurfaceFlinger(570): renderer : Android PixelFlinger 1.0
09-07 06:22:04.148: INFO/SurfaceFlinger(570): version : OpenGL ES-CM 1.0
09-07 06:22:04.148: INFO/SurfaceFlinger(570): extensions: GL_OES_byte_coordinates GL_OES_fixed_point GL_OES_single_precision GL_OES_read_format GL_OES_compressed_paletted_texture GL_OES_draw_texture GL_OES_matrix_get GL_OES_query_matrix GL_ARB_texture_compression GL_ARB_texture_non_power_of_two GL_ANDROID_direct_texture GL_ANDROID_user_clip_plane GL_ANDROID_vertex_buffer_object GL_ANDROID_generate_mipmap
09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/copybit.goldfish.so error=Cannot find library
09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/copybit.default.so error=Cannot find library
09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/overlay.goldfish.so error=Cannot find library
09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/overlay.default.so error=Cannot find library
09-07 06:22:04.167: INFO/sysproc(570): System server: starting Android runtime.
09-07 06:22:04.167: INFO/sysproc(570): System server: starting Android services.
09-07 06:22:04.179: INFO/SystemServer(570): Entered the Android system server!
09-07 06:22:04.209: INFO/sysproc(570): System server: entering thread pool.
09-07 06:22:04.267: ERROR/GLLogger(570): couldn't load <libhgl.so> library (Cannot find library)
09-07 06:22:04.338: INFO/SystemServer(570): Starting Power Manager.
09-07 06:22:04.387: INFO/ARMAssembler(570): generated scanline__00000077:03545404_00000A01_00000000 [ 30 ipp] (51 ins) at [0x190ed0:0x190f9c] in 6840752 ns
09-07 06:22:04.397: INFO/SystemServer(570): Starting Activity Manager.
09-07 06:22:04.578: INFO/SystemServer(570): Starting telephony registry
09-07 06:22:04.588: INFO/SystemServer(570): Starting Package Manager.
09-07 06:22:04.619: INFO/Installer(570): connecting...
09-07 06:22:04.619: INFO/installd(543): new connection
......
当然,这里的信息足够多的,有兴趣的朋友不妨用这种方法去理解和研究一下android启动过程。