继System进程的启动流程第二部分之后,我们来分析Launcher进程的启动。
public class Process {
......
public static final int start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags,
String[] zygoteArgs)
{
if (supportsProcesses()) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
......
}
} else {
......
return 0;
}
}
......
}
调用startViaZygote函数进一步操作。
public class Process {
......
private static int startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags,
String[] extraArgs)
throws ZygoteStartFailedEx {
int pid;
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_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");
}
//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);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
pid = zygoteSendArgsAndGetPid(argsForZygote);
}
}
......
}
这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。
public class Process {
......
private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
throws ZygoteStartFailedEx {
int pid;
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.
*/
sZygoteWriter.write(Integer.toString(args.size()));//向Zygote进程发送通信数据
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();
// Should there be a timeout on this?
pid = sZygoteInputStream.readInt();
if (pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
} catch (IOException ex) {
......
}
return pid;
}
......
}
这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:
public class Process {
......
/**
* Tries to open socket to Zygote process if not already open. If
* already open, does nothing. May block and retry.
*/
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 {
sZygoteSocket = new LocalSocket();//创建一个LocalSocket对象
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));//和设备文件/dev/socket/zygote绑定,就相当于与Zygote进程中名称为"zygote"的Socket建立了连接
sZygoteInputStream
= new DataInputStream(sZygoteSocket.getInputStream());//输入流,以便获得Zygote进程发送过来的通信数据
sZygoteWriter =
new BufferedWriter(
new OutputStreamWriter(
sZygoteSocket.getOutputStream()),//输出流,以便可以向Zygote进程发送通信数据
256);
Log.i("Zygote", "Process: zygote socket opened");
sPreviousZygoteOpenFailed = false;
break;
} catch (IOException ex) {
......
}
}
......
}
......
}
Process类有一个类型为LocalSocket的静态成员变量sZygoteSocket,它是Zygote进程中一个名称为"zygote"的Socket建立连接的。Zygote进程在启动时,会在内部创建一个名称为"zygote”的Socket,这个Socket是与设备文件/dev/socket/zygote绑定在一起的。
这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。
当将数据通过Socket接口发送出去后,就会执行下面这个语句:
done = peers.get(index).runOnce();
这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.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);
详情请参考
Dalvik虚拟机进程和线程的创建过程分析。
applyRlimitSecurityPolicy用于安全检查,只有System进程和root进程才能请求Zygote进程,让它创建进程。
private static void applyRlimitSecurityPolicy(
Arguments args, Credentials peer)
throws ZygoteSecurityException {
int peerUid = peer.getUid();
if (!(peerUid == 0 || peerUid == Process.SYSTEM_UID)) {
// All peers with UID other than root or SYSTEM_UID
if (args.rlimits != null) {
throw new ZygoteSecurityException(
"This UID may not specify rlimits.");
}
}
}
还有一处安全问题需要注意,现在uid为0,但是在forkAndSpecializeCommon中fork后,又自降uid了。
/*
* Utility routine to fork zygote and specialize the child process.
*/
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
pid_t pid;
uid_t uid = (uid_t) args[0];
gid_t gid = (gid_t) args[1];
ArrayObject* gids = (ArrayObject *)args[2];
u4 debugFlags = args[3];
ArrayObject *rlimits = (ArrayObject *)args[4];
int64_t permittedCapabilities, effectiveCapabilities;
if (isSystemServer) {
/*
* Don't use GET_ARG_LONG here for now. gcc is generating code
* that uses register d8 as a temporary, and that's coming out
* scrambled in the child process. b/3138621
*/
//permittedCapabilities = GET_ARG_LONG(args, 5);
//effectiveCapabilities = GET_ARG_LONG(args, 7);
permittedCapabilities = args[5] | (int64_t) args[6] << 32;
effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
} else {
permittedCapabilities = effectiveCapabilities = 0;
}
if (!gDvm.zygote) {
......
return -1;
}
......
pid = fork();
if (pid == 0) {
int err;
......
err = setgroupsIntarray(gids);
......
err = setrlimitsFromArray(rlimits);
......
err = setgid(gid);
......
err = setuid(uid);
......
err = setCapabilities(permittedCapabilities, effectiveCapabilities);
......
enableDebugFeatures(debugFlags);
......
gDvm.zygote = false;
if (!dvmInitAfterZygote()) {
......
dvmAbort();
}
} else if (pid > 0) {
/* the parent process */
}
return pid;
}
返回到runOnce,我们先来看父进程Zygote的执行路线。
private boolean handleParentProc(int pid,
FileDescriptor[] descriptors, Arguments parsedArgs) {
if(pid > 0) {
// Try to move the new child into the peer's process group.
try {
ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid()));
} catch (IOException ex) {
// This exception is expected in the case where
// the peer is not in our session
// TODO get rid of this log message in the case where
// getsid(0) != getsid(peer.getPid())
Log.i(TAG, "Zygote: setpgid failed. This is "
+ "normal if peer is not in our session");
}
}
try {
if (descriptors != null) {
for (FileDescriptor fd: descriptors) {
ZygoteInit.closeDescriptor(fd);
}
}
} catch (IOException ex) {
Log.e(TAG, "Error closing passed descriptors in "
+ "parent process", ex);
}
try {
mSocketOutStream.writeInt(pid);//向System进程写回pid
} catch (IOException ex) {
Log.e(TAG, "Error reading from command socket", ex);
return true;
}
/*
* If the peer wants to use the socket to wait on the
* newly spawned process, then we're all done.
*/
if (parsedArgs.peerWait) {
try {
mSocket.close();
} catch (IOException ex) {
Log.e(TAG, "Zygote: error closing sockets", ex);
}
return true;
}
return false;
}
还记得,zygoteSendArgsAndGetPid中:
pid = sZygoteInputStream.readInt();
System进程在等待获得Zygote进程发送过来的通信数据,此时可以返回了。
返回后System进程就可以调用Looper.loop()启动子线程的消息处理机制。如下所示:
class ServerThread extends Thread {
@Override
public void run() {
......
Looper.prepare();
......
try {
......
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
......
Slog.i(TAG, "Package Manager");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);//以后分析
ActivityManagerService.setSystemProcess();
......
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady(new Runnable() {
public void run() {
}
});
......
} catch (RuntimeException e) {
Slog.e("System", "Failure starting core service", e);
}
......
Looper.loop();
Slog.d(TAG, "System ServerThread is exiting!");
}
}
Zygote进程同时也处理完,在Socket端口继续等待请求。
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);
}
......
}
zygoteInitNative开启了子线程的Binder线程池,请参考
System进程的启动流程第一部分。
invokeStaticMain也参考System进程的启动流程第一部分。开始执行android.app.ActivityThread类的main函数。
public final class ActivityThread {
......
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
......
}
从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:
ActivityThread thread = new ActivityThread();
然后进入主线程消息循环中:
Looper.prepareMainLooper();
Looper.loop();
下一节Home界面的启动中我们将分析,如下代码
ActivityThread thread = new ActivityThread();
thread.attach(false);