概述:
在Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由Zygote进程负责创建的,因此,我们将它成为进程孵化器。Zygote进程是通过复制自身的方式来创建System进程和应用程序进程。由于Zygote进程在启动时会在内部创建一个虚拟机实例,因此,通过复制Zygote进程而得到的System进程和应用程序进程可以快速地在内部获得一个虚拟机实例拷贝。
Zygote进程启动完成以后,会马上将system进程启动起来,以便它可以将系统关键服务启动起来。
init 进程概述:
init进程是Android启动后的,由内核启动的第一个用户级进程
Android 的init进程提供四大功能:
- init进程处理子进程的终止与再启动
- init 进程分析init.rc 启动脚本文件,并根据相关中包含的内容,执行相应的功能;
- init进程提供属性服务;
- init进程生成设备节点文件
11. 1 zygote进程的启动脚本
Zygote进程是由Android系统的第一个进程init启动起来的。init进程是在内核加载完成之后就启动起来的(也就是用户空间的第一个进程),它的启动过程中,会读取根目录下的一个脚本文件init.rc,以便可以将其他需要开启的进程也一起启动起来。
Zygote进程在脚本文件init.rc 中的启动脚本
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
第一行表示Zygote进程是以服务的形式启动的,并且它所对应的应用程序文件为 /system/bin/app_process。接下来的四个选项是Zygote进程的启动参数,其中,
最后一个参数 "--start-system-server" 表示Zygote进程在启动完成之后,需要马上将System进程也启动起来。
第二行表示Zygote进程在启动的过程中,需要再内部创建一个名称为 "zygote" 的socket。这个Socket是用来执行进程间通信的,
它的访问权限被这只为666,即所有用户都可以对它进行读写。
由于Zygote进程在脚本文件init.rc中配置了以服务的形式来启动,因此,init进程在启动时,就会调用函数service_start来启动它,
11.2 Zygote 进程的启动过程
app_main.cpp # main
int main(int argc, const char* const argv[])
{
...
// Next arg is startup classname or "--zygote"
if (i < argc) {
arg = argv[i++];
// zygote 启动流程
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 {
....
}
} else {
....
}
}
通过AppRuntime (父类:AndroidRuntime) 来启动java 虚拟机,运行com.android.internal.os.ZygoteInit 的main函数
AndroidRuntime.cpp # start
来启动java 虚拟机,运行com.android.internal.os.ZygoteInit 的main函数
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
blockSigpipe();
/*
* 'startSystemServer == true' means runtime is obslete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
if (startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
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.");
goto bail;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/*
* Register android functions.
*/
if (startReg(env) < 0) {
LOGE("Unable to register all android natives\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) {
...
} else {
startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
...
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
...
}
}
...
bail:
free(slashClassName);
}
ZygoteInit # main
public static void main(String argv[]) {
try {
VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
// 创建一个Server端Socket, 等待 ActivityManagerservice 的请求来创建新的进程。
registerZygoteSocket();
preloadClasses();
//cacheRegisterMaps();
preloadResources();
// Do an initial gc to clean up after startup
gc();
if (argv[1].equals("true")) {
// 启动 system server
startSystemServer();
}
// ZYGOTE_FORK_MODE 的值默认为true
if (ZYGOTE_FORK_MODE) {
// 调用这个函数,来等待ActivityManagerService 请求Zygote进程创建新的应用程序。
// 不过,这种情况下,对于每一个请求,Zygote进程都会创建一个新的进程来处理,这样会浪费大量的进程资源。
// 因此, 为了让所有的创建应用程序进程请求都在同一个进程中处理,我们将ZygoteInit类的静态成员变量 ZYGOTE_FORK_MODE 设置为false
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) { ... } catch (RuntimeException ex) { ... }
}
ZygoteInit#startSystemServer
启动System Server 进程
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
// 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,3001,3002,3003",
"--capabilities=130104352,130104352",
"--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,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
return true;
}
System Server 进程的启动
由于System进程复制了Zygote进程的地址空间,因此它就会获得Zygote进程在启动过程中创建的一个socket。System进程不需要使用这个Socket,因此,需要调用closeServerSocket 来关闭它。
接下来需要调用RuntimeInit 的 zygoteInit 来进一步启动System进程。
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/* should never reach here */
}
RuntimeInit # zygoteInit
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in finishInit()
* were rationalized with Zygote startup.
*
* Current recognized args:
*
* - --nice-name=nice name to appear in ps
*
-
[--] <start class name> <args>
*
*
* @param argv arg strings
*/
public static final void zygoteInit(String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// 设置System进程的回去和键盘布局等通用信息
commonInit();
// 在System进程中启动一个Binder线程池
zygoteInitNative();
int curArg = 0;
for ( /* curArg */ ; curArg < argv.length; curArg++) {
String arg = argv[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
} else if (arg.startsWith("--nice-name=")) {
String niceName = arg.substring(arg.indexOf('=') + 1);
Process.setArgV0(niceName);
}
}
if (curArg == argv.length) {
Slog.e(TAG, "Missing classname argument to RuntimeInit!");
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
// 启动 com.android.server.SystemServer类的main函数
invokeStaticMain(startClass, startArgs);
}
SystemServer # main
进入SystemServer进程的java世界
public static void main(String[] args) {
// 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);
System.loadLibrary("android_servers");
// 启动一些使用C++语言开发的系统服务,
// com_android_server_SystemServer.cpp
// android_server_SystemServer_init1 方法
init1(args);
}
system_init.cpp # system_init
extern "C" status_t system_init()
{
LOGI("Entered system_init()");
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
LOGI("ServiceManager: %p\n", sm.get());
sp grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
// Start the sensor service
SensorService::instantiate();
// On the simulator, audioflinger et al don't get started the
// same way as on the device, and we need to start them here
if (!proc->supportsProcesses()) {
// Start the AudioFlinger
AudioFlinger::instantiate();
// Start the media playback service
MediaPlayerService::instantiate();
// Start the camera service
CameraService::instantiate();
// Start the audio policy service
AudioPolicyService::instantiate();
}
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
LOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
LOGI("System server: starting Android services.\n");
runtime->callStatic("com/android/server/SystemServer", "init2");
// If running in our own process, just go into the thread
// pool. Otherwise, call the initialization finished
// func to let this process continue its initilization.
if (proc->supportsProcesses()) {
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
}
return NO_ERROR;
}
SystemServer#init2
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
SystemServer#ServerThread#
@Override
public void run() {
Looper.prepare();
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");
...
}
});
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}