3. ZygoteConnection.runOnce
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
try {
//读取socket客户端发送过来的参数列表
args = readArgumentList();
} catch (IOException ex) {
closeSocket();
return true;
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
//将binder客户端传递过来的参数,解析成Arguments对象格式
parsedArgs = new Arguments(args);
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (Exception e) {
...
}
try {
if (pid == 0) {
//子进程执行
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// 不应到达此处,子进程预期的是抛出异常ZygoteInit.MethodAndArgsCaller或者执行exec().
return true;
} else {
//父进程执行
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
4. forkAndSpecialize
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
...
VM_HOOKS.postForkCommon();
return pid;
}
VM_HOOKS.preFork()的主要功能便是停止Zygote的4个Daemon子线程的运行,等待并确保Zygote是单线程(用于提升fork效率),并等待这些线程的停止,初始化gc堆的工作, 并将线程转换为long型并保存到token
public void preFork() {
Daemons.stop(); //停止4个Daemon子线程【见小节8.1】
waitUntilAllThreadsStopped(); //等待所有子线程结束【见小节8.2】
token = nativePreFork(); //完成gc堆的初始化工作【见小节8.3】
}
nativeForkAndSpecialize()调用fork()创建新进程,设置新进程的主线程id,重置gc性能数据,设置信号处理函数等功能。
com_android_internal_os_Zygote_nativeForkAndSpecialize()
ForkAndSpecializeCommon()
fork() //fork子进程
//等价于调用zygote.callPostForkChildHooks()
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,is_system_server ? NULL : instructionSet);
fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次,返回值有3种类型。
- 父进程中,fork返回新创建的子进程的pid;
- 子进程中,fork返回0;
- 当出现错误时,fork返回负数。(当进程数超过上限或者系统内存不足时会出错)
fork()的主要工作是寻找空闲的进程号pid,然后从父进程拷贝进程信息,例如数据段和代码段,fork()后子进程要执行的代码等。 Zygote进程是所有Android进程的母体,包括system_server和各个App进程。zygote利用fork()方法生成新进程,对于新进程A复用Zygote进程本身的资源,再加上新进程A相关的资源,构成新的应用进程A。其中下图中Zygote进程的libc、vm、preloaded classes、preloaded resources是如何生成的
copy-on-write过程:当父子进程任一方修改内存数据时(这是on-write时机),才发生缺页中断,从而分配新的物理内存(这是copy操作)。
copy-on-write原理:写时拷贝是指子进程与父进程的页表都所指向同一个块物理内存,fork过程只拷贝父进程的页表,并标记这些页表是只读的。父子进程共用同一份物理内存,如果父子进程任一方想要修改这块物理内存,那么会触发缺页异常(page fault),Linux收到该中断便会创建新的物理内存,并将两个物理内存标记设置为可写状态,从而父子进程都有各自独立的物理内存。
VM_HOOKS.postForkCommon的主要功能是在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。
Zygote.forkAndSpecialize时序图
到此App进程已完成了创建的所有工作,接下来开始新创建的App进程的工作。在前面ZygoteConnection.runOnce方法中,zygote进程执行完
forkAndSpecialize()后,新创建的App进程便进入handleChildProc()方法,下面的操作运行在App进程。
三. 新进程运行
在前面runOnce()过程中调用forkAndSpecialize()创建完新进程后,返回值pid=0(即运行在子进程)继续开始执行handleChildProc()方法。
1.handleChildProc
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {
//关闭Zygote的socket两端的连接
closeSocket();
ZygoteInit.closeServerSocket();
if (parsedArgs.niceName != null) {
//设置进程名
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
//这是用于检测进程内存泄露或溢出时场景而设计
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
//执行目标类的main()方法
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null);
}
}
2. zygoteInit
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
redirectLogStreams(); //重定向log输出
commonInit(); // 通用的一些初始化
nativeZygoteInit(); // zygote初始化
applicationInit(targetSdkVersion, argv, classLoader); // 应用初始化
}
2.1 commonInit
private static final void commonInit() {
// 设置默认的未捕捉异常处理方法
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
// 设置市区,中国时区为"Asia/Shanghai"
TimezoneGetter.setInstance(new TimezoneGetter() {
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
//重置log配置
LogManager.getLogManager().reset();
new AndroidConfig();
// 设置默认的HTTP User-agent格式,用于 HttpURLConnection。
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
// 设置socket的tag,用于网络流量统计
NetworkManagementSocketTagger.install();
}
2.2 nativeZygoteInit
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) {
//此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
gCurRuntime->onZygoteInit();
}
virtual void onZygoteInit() {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool(); //启动新binder线程
}
- ProcessState::self():主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver().
- startThreadPool(): 启动Binder线程池,
2.3 applicationInit
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
//true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
nativeSetExitWithoutCleanup(true);
//设置虚拟机的内存利用率参数值为0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
final Arguments args;
try {
args = new Arguments(argv); //解析参数
} catch (IllegalArgumentException ex) {
return;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//调用startClass的static方法 main()
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
此处args.startClass为”android.app.ActivityThread”。
Android Framwork ---App进程启动(上)