我们知道,当ActivityManagerService发现用来启动一个组件的进程不存在时,就会请求Zygote生成一个新的进程,并且在该进程中加载该组件的实例。而从Zygote的启动过程中得知,ActivityManagerService和Zygote进程是通过Socket来通信的,而Zygote当收到连接请求时候,会fork一个新的进程。
在这篇文章中,我们来分析一下这个过程。
和这部门相关的源码文件如下所示:
ActivityManagerNative.java 位于 frameworks/base/core/java/android/app/ActivityManagerNative.java
ActivityManagerService 位于 frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
Process.java 位于 frameworks/base/core/java/android/os/Process.java
LocalServerSocket.java 位于 frameworks/base/core/java/android/net/LocalServerSocket.java
LocalSocketImpl.java 位于frameworks/base/core/java/android/net/LocalSocketImpl.java
android_net_LocalSocketImpl.cpp 位于 frameworks/base/core/jni/ android_net_LocalSocketImpl.cppZygoteConnection.java 位于frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
当ActivityManagerService发现确实需要一个新进程的时候,就会调用Process.start函数来启动一个新的进程,
Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null)
并指定入口函数为android.app.ActivityThread的main函数。我们就从
Process的start函数来开始分析启动新进程的过程:
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 {
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来和Zygote建立连接,
startViaZygote的实现如下:
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) {
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);
}
}
return zygoteSendArgsAndGetResult(argsForZygote);
}
}
在startViaZygote函数中,会首先将参数收集起来,最后会调用zygoteSendArgsAndGetResult函数来继续启动新进程。zygoteSendArgsAndGetResult函数的实现如下:
private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
//建立连接
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.
*/
//写入参数
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();
//保存新进程的pid
ProcessStartResult result = new 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);
}
}
在zygoteSendArgsAndGetResult函数中,会首先建立连接,接着将参数发送给Zygote进程,并等待返回,最后保存新进程的pid。
我们先来看一下建立连接的过程,这是通过调用openZygoteSocketIfNeeded函数来实现的,openZygoteSocketIfNeeded的实现如下:
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 {
//生成一个LocalSocket
sZygoteSocket = new LocalSocket();
//连接
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());
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");
}
}
在
openZygoteSocketIfNeeded函数中,会生成一个LocalSocket对象,在LocalSocket对象中有一个LocalSocketImpl的成员变量。接着就会调用LocalSocket的connect函数来进行和Zygote进程的连接,LocalSocket的connect函数实现如下:
public void connect(LocalSocketAddress endpoint) throws IOException {
synchronized (this) {
if (isConnected) {
throw new IOException("already connected");
}
implCreateIfNeeded();
impl.connect(endpoint, 0);
isConnected = true;
isBound = true;
}
}
在
LocalSocket的
connect函数中,会调用成员变量impl的connect函数,因此我们接下来看一下LocalSocketImpl的connect函数的实现:
protected void connect(LocalSocketAddress address, int timeout)
throws IOException
{
if (fd == null) {
throw new IOException("socket not created");
}
//进一步 执行 连接操作
connectLocal(fd, address.getName(), address.getNamespace().getId());
}
在
connect函数中会调用connectLocal来继续执行连接的操作,connectLocal函数是个native函数,
private native void connectLocal(FileDescriptor fd, String name,
int namespace) throws IOException;
调用
connectLocal函数,实际上是调用的android_net_LocalSocketImpl.cpp的socket_connect_local函数,在socket_connect_local函数中会执行连接的操作。
当和Zygote进程建立完Socket之后,就会将参数发送给Zygote进程。这时候,ZygoteInit的runSelectLoopMode函数中就会收到连接请求,这时候ZygoteConnection的runOnce函数就会被调用来响应该连接。我们来看一看runOnce函数的实现:
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);
}
//fork一个新进程
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;
//对子进程进行一些初始化的操作
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);
}
}
在runOnce函数中,会首先读取启动的参数,接着fork一个新进程,最后在新的进程中调用handleChildProc来对新进程进行一些初始化的操作。
handleChildProc函数的实现如下:
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
/*
* Close the socket, unless we're in "peer wait" mode, in which
* case it's used to track the liveness of this process.
*/
if (parsedArgs.peerWait) {
try {
ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true);
sPeerWaitSocket = mSocket;
} catch (IOException ex) {
Log.e(TAG, "Zygote Child: error setting peer wait "
+ "socket to be close-on-exec", ex);
}
} else {
//关闭socket
closeSocket();
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);
}
//需要在启动的时候 初始化
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
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);
}
}
}
}
在handleChildProc函数中,会调用RuntimeInit的zygoteInit函数来执行初始化的操作。
RuntimeInit的
zygoteInit函数的执行过程,我们在SystemServer进程的启动过程分析时已经分析过了。只不过这里在执行applicationInit函数的时候,调用invokeStaticMain是,传递的参数为"android.app.ActivityThread",也就是说这里执行的是android.app.ActivityThread的main函数:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在
android.app.ActivityThread的main函数中,主要完成的工作就是启动了一个Looper。
这样,我们就分析了应用程序进程的启动过程。