Android Framework 学习笔记(六)应用程序进程启动过程
private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
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?
ProcessStartResult result = new Process
StartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
zygoteSendArgsAndGetResult 函数主要做的就是将传入的应用进程的启动参数 argsForZygote 写入到 ZygoteState 中,结合上文我们知道 ZygoteState 其实是由 openZygoteSocketIfNeeded 函数返回的,那么我们接着来看 openZygoteSocketIfNeeded 函数。
Process#openZygoteSocketIfNeeded()
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); //1
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); //2
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
在之前讲 Zygote 进程启动过程时我们得知,在 Zygote 的 main 函数中会创建 name 为“zygote”的 Server 端 Socket。
注释 1 处会调用 ZygoteState 的 connect 函数与名称为 ZYGOTE_SOCKET 的 Socket 建立连接,这里 ZYGOTE_SOCKET 的值为“zygote”。
注释 2 处如果连接 name 为“zygote”的 Socket 返回的 primaryZygoteState 与当前的 abi 不匹配,则会连接 name 为“zygote_secondary”的 Socket。这两个 Socket 区别就是:name 为”zygote”的 Socket 是运行在 64 位 Zygote 进程中的,而 name 为“zygote_secondary”的 Socket 则运行在 32 位 Zygote 进程中。既然应用程序进程是通过 Zygote 进程 fock 产生的,当要连接 Zygote 中的 Socket 时,也需要保证位数的一致。
接收请求并创建应用程序进程
Socket 进行连接成功并匹配 abi 后会返回 ZygoteState 类型对象,我们在分析 zygoteSendArgsAndGetResult 函数中讲过,会将应用进程的启动参数 argsForZygote 写入到 ZygoteState 中,这样 Zygote 进程就会收到一个创建新的应用程序进程的请求,我们回到 ZygoteInit 的 main 函数。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit#main()
public static void main(String argv[]) {
...
try {
String socketName = "zygote";
/*注册 Zygote 用的 Socket/
registerZygoteSocket(socketName); //1
//预加载类和资源
preload(); //2
...
//启动 SystemServer 进程
if (startSystemServer) {
startSystemServer(abiList, socketName); //3
}
//监听 socket,启动新的应用进程
runSelectLoop(abiList); //4
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
//通过反射调用 SystemServer#main()
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
注释 1 处通过 registerZygoteSocket 函数来创建一个 Server 端的 Socket,这个 name 为”zygote”的 Socket 用来等待 AMS 来请求 Zygote 来创建新的应用程序进程。
注释 2 处用来预加载类和资源。
注释 3 处用来启动 SystemServer 进程,这样系统的关键服务也会由 SystemServer 进程启动起来。
注释 4 处调用 runSelectLoop 函数来等待 AMS 的请求。
ZygoteInit#runSelectLoop()
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(sServerSocket.getFileDescriptor()); //1
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) { //2
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) { //3
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList); //4
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce(); //5
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
private static ZygoteConnection acceptCommandPeer(String abiList) {
try {
return new ZygoteConnection(sServerSocket.accept(), abiList);
} catch (IOException ex) {
...
}
}
注释 1 处中的 sServerSocket 就是我们在 registerZygoteSocket 函数中创建的服务端 Socket,调用 sServerSocket.getFileDescriptor()用来获得该 Socket 的 fd 字段的值并添加到 fd 列表 fds 中。接下来无限循环用来等待 AMS 请求 Zygote 进程创建新的应用程序进程。
注释 2 处通过遍历将 fds 存储的信息转移到 pollFds 数组中。
注释 3 处对 pollFds 进行遍历。
注释 4 如果 i==0 则说明服务端 Socket 与客户端连接上,也就是当前 Zygote 进程与 AMS 建立了连接,则通过 acceptCommandPeer 函数得到 ZygoteConnection 类并添加到 Socket 连接列表 peers 中,接着将该 ZygoteConnection 的 fd 添加到 fd 列表 fds 中,以便可以接收到 AMS 发送过来的请求。
注释 5 如果 i 的值大于 0,则说明 AMS 向 Zygote 进程发送了一个创建应用进程的请求,则调用 ZygoteConnection 的 runOnce 函数来创建一个新的应用程序进程。并在成功创建后将这个连接从 Socket 连接列表 peers 和 fd 列表 fds 中清除。
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
ZygoteConnection#runOnce()
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList(); //1
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
...
try {
parsedArgs = new Arguments(args);//2
...
//3
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} catch (ErrnoException ex) {
....
}
try {
//4
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
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);
}
}
注释 1 处调用 readArgumentList 函数来获取应用程序进程的启动参数。注释 2 处将 readArgumentList 函数返回的字符串封装到 Arguments 对象 parsedArgs 中。
注释 3 处调用 Zygote 的 forkAndSpecialize 函数来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pid。
注释 4 处 forkAndSpecialize 函数主要是通过 fork 当前进程来创建一个子进程的,如果 pid 等于 0,则说明是在新创建的子进程中执行的,就会调用 handleChildProc 函数来启动这个子进程也就是应用程序进程。
ZygoteConnection#handleChildProc()
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
...
//1
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
}
注释 1 处由于 parsedArgs.invokeWith 属性默认为 null,最后调用 RuntimeInit.zygoteInit 函数。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
RuntimeInit#zygoteInit()
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit(); //1
applicationInit(targetSdkVersion, argv, classLoader); //2
}
注释 1 处会在新创建的应用程序进程中创建 Binder 线程池。
注释 2 处调用了 applicationInit 函数。
RuntimeInit#applicationInit()
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
// 初始化虚拟机环境
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs, classLoader); //1
}
注释 1 处 applicationInit 函数中主要调用了 invokeStaticMain 函数,需要注意的是第一个参数 args.startClass,这里指的就是前面赋值的 android.app.ActivityThread。
RuntimeInit#invokeStaticMain()
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader); //1
} catch (ClassNotFoundException ex) {
throw new RuntimeException("Missing class when invoking static main " + className, ex);
}
Method m;
try {
// 获取 main 方法
m = cl.getMethod("main", new Class[] { String[].class }); //2
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException("Problem getting static main on " + className, ex);
}
// 判断修饰符
int modifiers = m.getModifiers(); //3
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}
/*
This throw gets caught in ZygoteInit.main(), which responds
by invoking the exception's run() method. This arrangement
clears up all the stack frames that were required in setting
up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv); //4
}
注释 1 处通过反射来获得 android.app.ActivityThread 类。
注释 2 处来获得 ActivityThread 的 main 函数。
注释 3 判断修饰符,必须是 static 而且必须是 public 类型。
注释 4 将找到的 main 函数传入到 MethodAndArgsCaller 异常中并抛出该异常。这个异常在 ZygoteInit#main()方法中捕获。这么做的作用是清除应用程序进程创建过程的调用栈。
ZygoteInit#main()
public static void main(String argv[]) {
try {
...
startSystemServer(abiList, socketName);
...
} catch (MethodAndArgsCaller caller) {
caller.run(); //1
}
}
在注释 1 处调用了 MethodAndArgsCaller 的 run 函数。
MethodAndArgsCaller
public static class MethodAndArgsCaller extends Exception
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 }); //1
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
注释 1 处通过反射调用了 android.app.ActivityThread#main(String[] args)。至此,Zygote 进程 fork 出 ActivityThread 进程,并成功调用 ActivityThread#main()。
frameworks/base/core/java/android/app/ActivityThread.java
ActivityThread#main()
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
...
Looper.prepareMainLooper();//1
ActivityThread thread = new ActivityThread();//2
thread.attach(false); //3
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler(); //4
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();//5
throw new RuntimeException("Main thread loop unexpectedly exited");
}
注释 1 处在当前应用程序进程中创建消息循环。
注释 2 处创建 ActivityThread 实例。
注释 4 处从 ActivityThread 获取 handler,这样就将 ActivityThread 关联到 Looper 和 MessageQueue 了。
注释 5 处调用 Looper 的 loop,使得 Looper 开始工作,开始处理消息。可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,用来方便的使用 Android 的异步消息处理机制。
关于 Android 的异步消息处理机制大家可以参考我这篇文章:Android 异步消息处理机制:Looper、Handler、Message。这里就不多说了。
如果你看过Framework学习(三)SyetemServer进程启动过程
这篇文章,你肯定会发现创建应用程序进程和创建 SyetemServer 进程的步骤如此类似,其实他们都是通过 Zygote 进程 fork 自身来实现的,当然步骤差不多了。唯一区别是一个最终调用到 SyetemServer 的 main 函数,另一个最终调用到 ActivityThread 的 main 函数。
之前说过:在 Android 系统中,启动四大组件中的任何一个都可以启动应用程序。但实际上应用程序入口方法只有 ActivityThread#main()一个。接着看 ActivityThread#main()方法。
注释 3 处调用了 ActivityThread#attach(false)。
ActivityThread#attach()
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread); //1
} catch (RemoteException ex) {
// Ignore
}
...
}
...
}
前面文章分析过 AMS 中的 Binder 机制:ActivityManagerNative.getDefault(),返回的其实是 AMS。注释 1 其实调用的是 AMS 的 attachApplication 方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityManagerService#attachApplication()
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid); //1
Binder.restoreCallingIdentity(origId);
}
}
注释 1 调用了两个参数的 attachApplicationLocked()方法
ActivityManagerService#attachApplicationLocked()
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) { //1
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
...
}
注释 1 调用 ActivityStackSupervisor 的 attachApplicationLocked 方法。
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
ActivityStackSupervisor#attachApplicationLocked()
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
评论