本来是要将之前Activity冷启动流程继续梳理清楚的,到了中间看到当进程尚未启动还需要启动新的进程,这也是需要梳理清楚的,于是就先将进程启动流程在源码层面给梳理一遍.
建议在进入源码阅读之前,先将上面的流程图大概的进行两遍左右的阅读,然后相信会对下面的源码梳理的理解有很大的帮助:
我们在开发中中应该知道,应用进程的管理通常是由AMS来进行的,但是进程的启动也是由AMS来发起的
【虽然是AMS发起的,但是创建却不是AMS,而是经由Zygote来实现的,(这点需要明确一下),下面会有基于源码层的详细介绍】
AMS中有一个 方法叫startProcess
,它就是AMS发起创建新的应用进程的开始,我们就进入到代码中看看:
frameworks/base/services/core/java/com/android/server/am.ActivityManagerService.java
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
...
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
checkTime(startTime, "startProcess: returned from zygote!");
return startResult;
...
}
startProcess()方法内部实现相对简单,主要就是通过调用Process的start()方法,我们就去Process中继续看看;
我们先说明一下,这个Process类,这个类主要就是用来管理Android系统的的进程。
frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(...) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
...
public static final ZygoteProcess zygoteProcess =
new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);
我们看到,当前的start()方法内部是通过调用ZygoteProcess的成员方法start();这个zygoteProcess的创建需要传递参数,我们注意到这个参数是SOCKET
字眼,恩恩,确实接下来需要使用到socket通信了;
我们这里再对ZygoteProcess这个类进行简单的说明,它是和Zygote进程通信,主要负责打开给zygote的socket,并连接。
frameworks/base/core/java/android/os/ZygoteProcess.java
public final Process.ProcessStartResult start(...) {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
zygoteArgs);
...
}
start()方法其实也没做啥,还是调用了一个成员变量startViaZygote(),我们就继续到startViaZygote()方法中;
frameworks/base/core/java/android/os/ZygoteProcess.java
*/
private Process.ProcessStartResult startViaZygote(....)
throws ZygoteStartFailedEx {
// 这是一个参数列表,用于向Zygote传递启动新的进程的参数
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
// --setgroups is a comma-separated list
// 省略代码,主要是参数的封装、
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
在startViaZygote()方法这种,我们首先注意这里创建了一个ArrayList,它里面就是填充由于启迪新的进程的参数,然后就会调用zygoteSendArgsAndGetResult()方法将参数传递进去,这里我们还看到,不光传入参数列表,还有个openZygoteSocketIfNeeded()
的方法,【这个方法就是用于打开和Zygote socket通信的】;紧接着我们到zygoteSendArgsAndGetResult()方法中:
frameworks/base/core/java/android/os/ZygoteProcess.java
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
....
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();
...
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
...
return result;
...
}
zygoteSendArgsAndGetResult()方法向zygote进程发送参数列表,然后zygote进程启动一个新子进程并返回子进程的pid。
到此,AMS发起应用创建的流程就结束了,我们接下来就需要了解Zygote是怎么接受消息并创建新的进程的;
在Zygote进程启动完成后,就会进入一个loop循环,Zygote就是在当前的循环中响应请求并处理,当我们的AMS向Zygote发送创建新进程的请求时,Zygote端就会fork一个新的进程。我们这就到代码中看看其实现:
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
...
while (true) {
....
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
....
return command;
...
}
...
}
}
runSelectLoop()方法在接收到来自AMS的请求后,马上就会调用ZygoteConnection的成员方法processOneCommand()进行处理;
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
//省略代码,主要工作是解析参数
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
...
try {
if (pid == 0) {
// in child
...
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote);
...
如上所示,在获取和解析完请求的参数后,zygote就会调用forkAndSpecialize()方法来创建新的进程,接下来我们就需要关心两个重点,
/frameworks/base/core/java/com/android/internal/os/Zygote.java
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
...
return pid;
}
如上所示,在Zygote的forkAndSpecialize()方法中,是调用的一个native
方法nativeForkAndSpecialize()
,那么我们就需要去了解native层的实现了;
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
jstring instructionSet, jstring appDataDir) {
jlong capabilities = 0;
...
return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE,
instructionSet, appDataDir);
}
....
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(...) {
...
pid_t pid = fork();
....
return pid;
}
如上所示,我们可以看到,com_android_internal_os_Zygote_nativeForkAndSpecialize()函数中调用ForkAndSpecializeCommon(),最后直接fork()
出子进程并返回。在新的进程中,就会调用handleChildProc()
进行进一步的初始化,
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
closeSocket();
...
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
...
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
null /* classLoader */);
...
}
}
如上所示,在新的进程中执行handleChildProc()方法,首先关闭socket,因为当前的socket使用Zygote继承下来的,但是新的进程不需要了,然后调用ZygoteInit的zygoteInit()方法继续执行。
到了这里,新的进程就已经创建完成了,但是还不能使用,因为我们当前的进程是从zygote直接继承下来的,很多初始化动作需要完成才能正常是使用,
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
...
// log初始化
RuntimeInit.redirectLogStreams();
// 一般功能的初始化
RuntimeInit.commonInit();
// 开启Binder线程池
ZygoteInit.nativeZygoteInit();
// 应用进程上层类的执行
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
如上所示,主要就是一些初始化的动作,这里我们关注一下binder线程池的创建过程;
nativeZygoteInit是一个navtive方法,实现如下在:
frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
上述代码最终会走到如下:
frameworks/base/cmds/app_process/app_main.cpp
class AppRuntime : public AndroidRuntime
{
...
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
...
}
如上所示,nativeZygoteInit()方法在底层的实现就是调用ProcessState的成员函数startThreadPool()
来创建Binder线程池,程序就可以进行bidner调用了,可以和AMS等进程进行通信。
紧接着,代码就会走到RuntimeInit的appliacationInit()方法中,我们继续查看其实现:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
...
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
...
// 找到要启动的类
cl = Class.forName(className, true, classLoader);
...
Method m;
...
// 找到其中的main方法
m = cl.getMethod("main", new Class[] { String[].class });
...
// 通过MethodAndArgsCaller来调用启动类的main方法(ActivityThread的Main方法
return new MethodAndArgsCaller(m, argv);
}
...
// MethodAndArgsCaller的实现
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
...
}
}
如上所示,applicationInit()方法里面主要是调用findStaticMain()方法,而findStaticMain()方法就像其名称一样,通过传入的参数拿到要启动的类名,然后通过MethodAndArgsCaller来调用其Main
方法,由于我们启动的是应用进程,这里就会调用ActivityThread的Main方法。
进程走到ActiviityThread中后,接下来就会向通过attach方法
向AMS注册,向其传递一个当前应用的代理对象的句柄,如此一来,AMS和应用之间就可以双向调用了。