Android应用程序进程启动过程的源代码分析(2)
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
-
public class ZygoteInit {
-
......
-
-
/**
-
* Runs the zygote process's select loop. Accepts new connections as
-
* they happen, and reads commands from connections one spawn-request's
-
* worth at a time.
-
*
-
* @throws MethodAndArgsCaller in a child process when a main() should
-
* be executed.
-
*/
-
private static void runSelectLoopMode() throws MethodAndArgsCaller {
-
ArrayList<FileDescriptor> fds = new ArrayList();
-
ArrayList<ZygoteConnection> peers = new ArrayList();
-
FileDescriptor[] fdArray = new FileDescriptor[4];
-
-
fds.add(sServerSocket.getFileDescriptor());
-
peers.add(null);
-
-
int loopCount = GC_LOOP_COUNT;
-
while (true) {
-
int index;
-
/*
-
* Call gc() before we block in select().
-
* It's work that has to be done anyway, and it's better
-
* to avoid making every child do it. It will also
-
* madvise() any free memory as a side-effect.
-
*
-
* Don't call it every time, because walking the entire
-
* heap is a lot of overhead to free a few hundred bytes.
-
*/
-
if (loopCount <= 0) {
-
gc();
-
loopCount = GC_LOOP_COUNT;
-
} else {
-
loopCount--;
-
}
-
-
-
try {
-
fdArray = fds.toArray(fdArray);
-
index = selectReadable(fdArray);
-
} catch (IOException ex) {
-
throw new RuntimeException("Error in select()", ex);
-
}
-
-
if (index < 0) {
-
throw new RuntimeException("Error in select()");
-
} else if (index == 0) {
-
ZygoteConnection newPeer = acceptCommandPeer();
-
peers.add(newPeer);
-
fds.add(newPeer.getFileDesciptor());
-
} else {
-
boolean done;
-
done = peers.get(index).runOnce();
-
-
if (done) {
-
peers.remove(index);
-
fds.remove(index);
-
}
-
}
-
}
-
}
-
-
......
-
}
-
done = peers.get(index).runOnce();
-
class ZygoteConnection {
-
......
-
-
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
-
String args[];
-
Arguments parsedArgs = null;
-
FileDescriptor[] descriptors;
-
-
try {
-
args = readArgumentList();
-
descriptors = mSocket.getAncillaryFileDescriptors();
-
} catch (IOException ex) {
-
......
-
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;
-
-
try {
-
parsedArgs = new Arguments(args);
-
-
applyUidSecurityPolicy(parsedArgs, peer);
-
applyDebuggerSecurityPolicy(parsedArgs);
-
applyRlimitSecurityPolicy(parsedArgs, peer);
-
applyCapabilitiesSecurityPolicy(parsedArgs, peer);
-
-
int[][] rlimits = null;
-
-
if (parsedArgs.rlimits != null) {
-
rlimits = parsedArgs.rlimits.toArray(intArray2d);
-
}
-
-
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
-
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
-
} catch (IllegalArgumentException ex) {
-
......
-
} catch (ZygoteSecurityException ex) {
-
......
-
}
-
-
if (pid == 0) {
-
// in child
-
handleChildProc(parsedArgs, descriptors, newStderr);
-
// should never happen
-
return true;
-
} else { /* pid != 0 */
-
// in parent...pid of < 0 means failure
-
return handleParentProc(pid, descriptors, parsedArgs);
-
}
-
}
-
-
......
-
}
-
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
-
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
-
if (pid == 0) {
-
// in child
-
handleChildProc(parsedArgs, descriptors, newStderr);
-
// should never happen
-
return true;
-
} else { /* pid != 0 */
-
......
-
}
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
-
class ZygoteConnection {
-
......
-
-
private void handleChildProc(Arguments parsedArgs,
-
FileDescriptor[] descriptors, PrintStream newStderr)
-
throws ZygoteInit.MethodAndArgsCaller {
-
......
-
-
if (parsedArgs.runtimeInit) {
-
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
-
} else {
-
......
-
}
-
}
-
-
......
-
}
-
public class RuntimeInit {
-
......
-
-
public static final void zygoteInit(String[] argv)
-
throws ZygoteInit.MethodAndArgsCaller {
-
// TODO: Doing this here works, but it seems kind of arbitrary. Find
-
// a better place. The goal is to set it up for applications, but not
-
// tools like am.
-
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
-
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
-
-
commonInit();
-
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);
-
invokeStaticMain(startClass, startArgs);
-
}
-
-
......
-
}
-
public class RuntimeInit {
-
......
-
-
public static final native void zygoteInitNative();
-
-
......
-
}
-
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
-
{
-
gCurRuntime->onZygoteInit();
-
}
-
static AndroidRuntime* gCurRuntime = NULL;
-
AndroidRuntime::AndroidRuntime()
-
{
-
......
-
-
assert(gCurRuntime == NULL); // one per process
-
gCurRuntime = this;
-
}
-
int main(int argc, const char* const argv[])
-
{
-
......
-
-
AppRuntime runtime;
-
-
......
-
}
-
class AppRuntime : public AndroidRuntime
-
{
-
......
-
-
};