Android进程启动过程源码分析整理.

来源:互联网 发布:威尔法瑞尔知乎 编辑:程序博客网 时间:2024/05/29 17:32
      文章仅仅用于个人的学习记录,基本上内容都是网上各个大神的杰作,此处摘录过来以自己的理解学习方
式记录一下。
       参考链接:
            http://blog.csdn.net/luoshengyang/article/details/6747696  罗升阳

1、概述.

       Android每启动一个应用程序就会新建一个进程,默认情况下,该应用程序的各个组件都会运行在同一个进程内,
   但是在manifest中相应的组件的节点下配置android:process属性也可以运行在不同的进程。那么启动一个应用程
   序是什么概念那?就是启动了一个activity或者service。此时假如是在新进程中启动的那么就回去创建这个进程。
   进程创建完毕以后会启动一个主线程然后进入循环来处理UI界面消息,此线程也成为UI线程。
       而我们又知道Android的应用程序是支持Binder通信的,binder它具有四个组件,分别是驱动程序、守护进程、
   Client以及Server,其中Server组件在初始化时必须进入一个循环中不断地与Binder驱动程序进行到交互,以便获
   得Client组件发送的请求,这个进入循环的操作也是系统帮我们执行完毕的.
 2、流程。
      ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的.那么为什么就突然说是从这里
   开始的那?其实等整理完毕Activity、service的启动流程就知道了,在启动它们的时候去判断是否是在一个新进程
   中打开的,是的话就调用这个接口。至于怎么判断是不是在新进程打开的,也在service/Activity启动的文章中分析.
      2.1、startProcessLocked()
           位于AMS当中,有几个重载的方法,我们以一个外部的调用的接口为切入点.
 // 这个info也很关键啊,里面有很多的应用的信息,由外部传入的.
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;//ProcessRecord 用来记录这个进程打开的信息.
if (!isolated) {//该进程是否是孤立的进程?暂发现大部分都是false,有一个是true.
//keepIfLarge空间足够的时候是否保存?难道是这个意思吗?
//一般的第一次走到这里返回的是null,由于以前没有创建过进程.
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
if (app != null && app.pid > 0) {//当该进程已经存在的时候.
if (!knownToBeDead || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: done, added package to proc");
return app;//不作处理返回.
}
 
// An application record is attached to a previous process,
// clean it up now.
if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG, "App died: " + app);
checkTime(startTime, "startProcess: bad proc running, killing");
Process.killProcessGroup(app.info.uid, app.pid);
handleAppDiedLocked(app, true, true);
checkTime(startTime, "startProcess: done killing old proc");
}
 
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
 
if (!isolated) {
if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mBadProcesses.get(info.processName, info.uid) != null) {
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ "/" + info.processName);
return null;
}
} else {
// When the user is explicitly starting a process, then clear its
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}
}
 
if (app == null) {//以前没有启动过!
checkTime(startTime, "startProcess: creating new process record");
//新建一个进程记录.
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.crashHandler = crashHandler;
//mProcessNames添加相应的赋值,这样下次get的时候就有了.
mProcessNames.put(processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
}
checkTime(startTime, "startProcess: done creating new process record");
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}
 
// If the system is not ready yet, then hold off on starting this
// process until it is.
if (!mProcessesReady //等系统完全启动起来再说,先放到了mProcessesOnHold.
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
checkTime(startTime, "startProcess: returning with proc on hold");
return app;
}
 
checkTime(startTime, "startProcess: stepping in to startProcess");
//最终又是调用重载的相关方法,进行进一步的处理.
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
//从上面的函数返回时,app已经有pid了.
return (app.pid != 0) ? app : null;
}
         关键的信息和参数有传入的:Application info 里面包含了很多的应用的信息,用于我么你初始化这个进程
      ,isSolated从Log看大部分都是传入的false.先是通过getProcessRecordLocked来尝试获取一下已经存在的进程
      记录,如果该记录没有存在的话就返回null,此时是第一次那么肯定会返回null.
//z获取已经存在的进程的记录.
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
if (uid == Process.SYSTEM_UID) {
......//系统进程的一些处理.
}
ProcessRecord proc = mProcessNames.get(processName, uid);//还没往里面添加所以返回null.
if (false && proc != null && !keepIfLarge
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY
&& proc.lastCachedPss >= 4000) {
.....//肯定不会走.
} else if (proc != null && !keepIfLarge
&& mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL
&& proc.setProcState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
......//如果有crash的就杀死这个进程.
}
return proc;//返回查询到的进程.
}
            mProcessNames是ProcessMap的类型,是一种封装的SparseArray,通过name和uid两个判断条件来获得Proce
         ssRecord.回到startProcessLocked当中,如果以前确实没有启动过,没有相关的进程记录,接下来就是调用
         newProcessRecordLocked()来为当前应用进程新建一个ProcessRecord.
//新建一个进程记录ProcessRecord.
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid) {
//customProcess没有指定的时候,就会info.processName
String proc = customProcess != null ? customProcess : info.processName;
.....
int uid = info.uid;
if (isolated) {
if (isolatedUid == 0) {
int userId = UserHandle.getUserId(uid);
int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
while (true) {
......
}
} else {
// Special case for startIsolatedProcess (internal only), where
// the uid of the isolated process is specified by the caller.
uid = isolatedUid;
}
}
return new ProcessRecord(stats, info, proc, uid);
}
            最主要得就是最后一句new ProcessRecord().去实例化了一个ProcessRecord对象,注意此时这个对象很
         多成员参数都还没赋值,比如它的关键变量int pid、IApplicationThread thread等,但此处传入一个很重
         要的变量final ApplicationInfo info.在构造中实例化了它,然后通过这个成员变量获取应用的信息.再次
         回到startProcessLocked当中.就是调用另外一个重载的startProcessLocked去进一步做处理了.
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
if (app.pid > 0 && app.pid != MY_PID) {
.....//此情景下由于还没有初始化pid所以pid肯定不大于0.
}
......
 
try {
//看样子是设置组件的存活状态. 第三个参数是true,代表存活.
AppGlobals.getPackageManager().setPackageAliveState(app.info.packageName,
app.processName, true, UserHandle.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
}
try {
int uid = app.uid;
 
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {//传入的相关参数是false.
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
......
} catch (PackageManager.NameNotFoundException e) {}
 
/*
* Add shared application and profile GIDs so applications can share some
* resources like shared libraries and access user-wide resources
*/
if (permGids == null) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
checkTime(startTime, "startProcess: building args");
......
int debugFlags = 0;
......//设置一些debugFlags方便调试.
app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;
 
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
checkTime(startTime, "startProcess: asking zygote to start proc");
//注意一下这个返回值的类型!!
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
//执行完Process.start()以后此时app.pid还未赋值.、
//从zygote进程返回了.
checkTime(startTime, "startProcess: returned from zygote!");
......
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
app.setPid(startResult.pid);//根据从zygote进程取回来的结果对app.pia进行相关的赋值.
......
synchronized (mPidsSelfLocked) {
//注意在这把pid加入到mPidsSelfLocked
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
checkTime(startTime, "startProcess: done updating pids map");
if ("activity".equals(hostingType) || "service".equals(hostingType)) {
mActivityTrigger.activityStartProcessTrigger(app.processName, startResult.pid);
}
} catch (RuntimeException e) {
app.setPid(0);//启动失败的时候设置pid为值为0
......
}
}
            受限制的一提的是它的entryPoint一般情况下都是"android.app.ActivityThread",直接是进程刚启动完
        毕后将要执行的类的main函数所在的地方.代表一个主线程.注意此时Process.start()的返回值类型,它是
        Process.ProcessStartResult
public static final class ProcessStartResult {
/**
* The PID of the newly started process.
* Always >= 0. (If the start failed, an exception will have been thrown instead.)
*/
public int pid;
 
/**
* True if the process was started with a wrapper attached.
*/
public boolean usingWrapper;
}
           我们需要重点关注的就是它的pid,它就是从zygote进程读回来的值,以供接下来的赋值处理.接下来分析
       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 abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {}
}
          就是直接调用内部函数startViaZygote() (via:通过).
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 abi,
String instructionSet,
String appDataDir,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
 
// --runtime-init, --setuid=, --setgid=,
// and --setgroups= must go first
//下面是创建进程的时候的各个参数
//如参数"--runtime-init"表示要为新创建的进程初始化运行时库
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);
}
 
if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}
 
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
 
argsForZygote.add(processClass);
 
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
//把各个参数组装好
android.util.Log.d("zy_pro","openZygoteSocketIfNeeded abi = "+abi);
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
          argsForZygote集合里面根据条件添加了各种的要传给zygote进程的参数.第一个就是"--runtime-init".每
       个参数的具体用意,应该是linux中fork进程时的参数.zygoteSendArgsAndGetResult(..),有两个参数,第一
       个是ZygoteState、第二个ArrayList的集合.ZygoteState:描述当前进程和zygote进程交互的状态.内部有输入
       、输出流、LocalSocket当成员变量和一些connect、close的方法等. LocalSocket用于创建一个不是服务端的
       位于Unix命名空间下的Socket.下面我们先看是如何获取ZygoteState的
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//ZYGOTE_SOCKET = "zygote"
} 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 {
//ZYGOTE_SOCKET = "zygote_secondary"
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} 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);
}
           primaryZygoteState是一个ZygoteState类型的变量,通过connect来创建一个socket,address = "zygote"
        回到zygoteSendArgsAndGetResult当中.
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
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.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
 
writer.write(Integer.toString(args.size()));
writer.newLine();
 
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
android.util.Log.d("zy_pro","Process arg = "+arg);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
 
writer.flush();//所有命令发送完毕
 
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
android.util.Log.d("zy_pro","Process result.pid = "+result.pid);
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
android.util.Log.d("zy_pro","Process result.usingWrapper = "+result.usingWrapper);
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
          通过zygoteState.writer的输出流往Socket中写入命令.最后通过result.pid = inputStream.readInt()来
      读取zygote进程创建完毕后的返回的进程的pid的值.不过注意最后的是Process.ProcessStartResult对象.
          在这里有一个疑惑?由于自身对socket的不了解.不明白为什么此处要用个socket,直接调用函数不行?暂
      时有课自欺欺人的认知,此处是算AMS所在的进程比如是"system"进程,它要去请求zygote进程去创建应用进程
      那么这就涉及到了进程通信,此处就用的socket来进行的进程通信.在socket流中有数据的时候读出来.(为什么
      不用binder那?应该是这种情况不是很合适吧?具体原理也不清楚)
         至此我们应该去哪看这个socket的另一端那?注释里面已经很清楚了.在com.android.internal.os.Zygote
     Init.readArgumentList()当中.我们先去ZygoteInit当中看看.搜索以后发现并没有readArgumentList.其实它是
     在ZygoteConnection.java当中。而出发条件确实在ZygoteInit中的runSelectLoop()在这个方法里面会循环监听
     前面的socket的请求.我们先来看一下ZygoteInit文件的main函数
public static void main(String argv[]) {//当fork一个zygote进程时,会进入.
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
 
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
 
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
 
registerZygoteSocket(socketName);//注册这个socket address = "zygote"
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
 
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
 
// Do an initial gc to clean up after startup
gc();
 
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
 
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
 
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);//循环去监听.
 
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();// 调用对于ActivityThread的main函数的时候的异常最终到了这里.
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
          注意当init进程fork一个zygote进程的时候最后会调用到这个文件的main函数当中,道理同ActivityThread.那么此时当前文
      件是运行在zygote进程的,也就是AMS所在的进程要向这个zygote进程请它再去创建进程,这就是一个跨进程通信.在这个main函
      数当中注册了socket,等待AMS的请求.接下来看看runSelectLoop.
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { //等待请求
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
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(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
//zy 当将数据通过Socket接口发送出去后走到这里.
//从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接
done = peers.get(index).runOnce();
 
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
         peers中存放的是ZygoteConnection,最终走到else分支调用done = peers.get(index).runOnce().调用ZygoteConnection的
      runOnce()此时还是在zygote的进程当中哦.
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
 
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
 
long startTime = SystemClock.elapsedRealtime();
 
try {
//这不就对应到前面的注释了嘛.
args = readArgumentList();//通过socket去读取写入到socket中的command
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
......
}
......
 
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
 
try {
parsedArgs = new Arguments(args);
......
FileDescriptor fd = mSocket.getFileDescriptor();
......
//下面是真正创建进程的地方.
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
.....
} catch (ZygoteSecurityException 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);
}
}
         先是调用readArgumentList()读取命令参数.
/**
* Reads an argument list from the command socket/
* @return Argument list or null if EOF is reached
* @throws IOException passed straight through
*/
private String[] readArgumentList()
throws IOException {
 
/**
* See android.os.Process.zygoteSendArgsAndGetPid()
* 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.
*/
 
int argc;
 
try {
String s = mSocketReader.readLine();
 
if (s == null) {
// EOF reached.
return null;
}
argc = Integer.parseInt(s);
} catch (NumberFormatException ex) {
Log.e(TAG, "invalid Zygote wire format: non-int at argc");
throw new IOException("invalid wire format");
}
 
// See bug 1092107: large argc can be used for a DOS attack
if (argc > MAX_ZYGOTE_ARGC) {
throw new IOException("max arg count exceeded");
}
 
String[] result = new String[argc];
for (int i = 0; i < argc; i++) {
result[i] = mSocketReader.readLine();
if (result[i] == null) {
// We got an unexpected EOF.
throw new IOException("truncated request");
}
}
 
return result;
}
          然后就是调用zygote的forkAndSpecialize.来实现真正的进程的创建,这个函数执行完后创建一个新进程,而且有两个返回   
      值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回。在当前进程中的返回值就是新
      创建的子进程的pid值,而在子进程中的返回值是0。(就当成fork出来的进程一模一样,然后函数就走到这里了,从这里往下执
      行).
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
......
int pid = nativeForkAndSpecialize( //直接调用到了native层的方法.
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
......
return pid;
}
         直接调用了native的方法,此处就是返回两个返回值的地方了. 
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir);
        回到ZygoteConnecttion的runOnce()方法当中 pid = Zygote.forkAndSpecialize(...)接着往下执行.
        我们先分析新建的这个进程的流程,也就是pid返回为0的这个分支。此时位于我们创建的子进程当中.执行handleChildProc
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
 
/**
* 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();
ZygoteInit.closeServerSocket();//先关闭socket
 
if (descriptors != null) {
......
}
 
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, null /* classLoader */);
}
} else {
......
}
}
          最终调用到RuntimeInit.java中的zygoteInit方法,我们进去看一下
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {//zy
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 
redirectLogStreams();
 
commonInit();
nativeZygoteInit();//执行Binder驱动程序初始化的相关工作了,服务端可以循环监听.
 
//进程创建完毕,调用argv对应类的入口的main函数."android.app.ActivityThread"
applicationInit(targetSdkVersion, argv, classLoader);
}
        最主要的就是两个方法,第一个nativeZygoteInit,该方法执行了该进程的Binder相关的初始化工作。其实就是建立了binder线程
    池来循环监听客户端的binder通信请求.最终通过nativeZygoteInit放调用到了AndroidRuntime.cpp中的com_android_internal_os_R
    untimeInit_nativeZygoteInit,然后又调用到了app_main.cpp中的onZygoteInit
virtual void onZygoteInit()
{
// Re-enable tracing now that we're no longer in Zygote.
atrace_set_tracing_enabled(true);
sp<ProcessState> proc = ProcessState::self();//看到了开启循环,然后一直和binder驱动打交道,监听客户端的请求.
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
        server组件在初始化时必须进入一个循环中不断地与Binder驱动程序进行到交互,以便获得Client组件发送的请
     求进入一个无限循环中与Binder驱动程序交互以便获得Client端的请求.通过以上方法调用,完成了假如它作为服务
     端的时候的binder的支持.(也就是native层实现binder的最后两步)
          至此完成了对binder通信的支持,解析来就是分析applicationInit(targetSdkVersion, argv, classLoader)的调用了.它那其
      实最终就是执行了我们前面传入的entrypoint = "android.app.ActivityThread"对应的main函数.
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
......
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
//启动某个java类的main函数.
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
         可以看到就是调用了invokeStaticMain传入相应的参数.
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
 
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
 
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
// 函数最后并没有直接调用这个静态成员函数main
} 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();
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.
*/
//抛出一个异常ZygoteInit.MethodAndArgsCaller,
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
          可以看此处的设计是直接抛出异常 ZygoteInit.MethodAndArgsCaller(m, argv).最终这个异常一层层返回到
    ZygoteInit.main函数.然后才去调用的android.app.ActivityThread类的main函数。看前面我们的ZygoteInit的main
    函数,捕获到异常以后调用caller.run()。也就是MethodAndArgsCaller的run.把"main"传过去.
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 {
//这样,android.app.ActivityThread类的main函数就被执行了
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
......
}
}
}
         这样知道此处才调用了对应类的main函数.关于ActivityThread的main函数我们单独分析过,启动了一个looper
     循环然后初始化了一些变量,最后初始化了ProcessRecord的thread变量.此时自己成的pid还未设置什么时候设置的
     那?想先跟前面你通过native方法fork进程的时候我们还有一条分支没有分析,那就是父类的那一条分支.我们处理
     一下.再回到zygote进程中的ZygoteConnection类的runOnce()进入到创建完毕的父类分支.执行handleParentProc()
     handleParentProc(pid, descriptors, serverPipeFd, parsedArgs)此时参数中的pid就是子类进程的pid.
private boolean handleParentProc(int pid,
FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {
 
if (pid > 0) {
setChildPgid(pid);
}
...... 
boolean usingWrapper = false;
......
try {
mSocketOutStream.writeInt(pid);//注意
mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
Log.e(TAG, "Error writing to command socket", ex);
return true;
}
 
return false;
}
         可以看到最终又往socket的输出流中写入pid.让客户端那边可以读取.然后阻碍AMS的进程中Process.java文件
      中zygoteSendArgsAndGetResult的类里面读取socket流里面的东西
            ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
android.util.Log.d("zy_pro","Process result.pid = "+result.pid);
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
android.util.Log.d("zy_pro","Process result.usingWrapper = "+result.usingWrapper);
return result;
         然后一层层返回到AMS的startProcessLocked当中继续Process.ProcessStartResult startResult = Process.
   start(......)往下执行.最终通过app.setPid(startResult.pid)来设置pid.这样就完成了基本的进程启动的功能.

            

0 0