目录
- 概述
- 总结
- 详细过程
- 问题&主要类说明
概述
-1-
在冷启动过程中,当“为App启动做完准备”之后( <<为目标App启动做准备>>),就需要检查App进程是否开启了,如果没有则需要先执行 App进程的创建操作。
-2-
当前源码的分析是基于 Android8.0。
总结
应用程序进程的启动可以是分为2个部分的。
第一部分:
AMS向Zygote进程发起启动app进程的请求。
1:AMS调用其内部的“startProcessLocked()”来开启启动app进程的入口。该方法主要做的是:组装发给zygote进城的用于启动子进程的参数列表(这些参数包括:uid,gid,entryPoint 参数等,entryPoint参数的值为ActivityThread的类全限定名。该参数用于fork子进程之后启动每个app进程的ActivityThread去做初始化操作。)
2:通过层层调用最终会执行ZygoteProcess.startViaZygote(),该方法首先会把AMS服务传过来的参数封装到一个argsForZygote参数列表中。
3:调用ZygoteProcess内部的openZygoteSocketIfNeeded()与Zygote进程建立Socket连接。
4:调用ZygoteProcess的zygoteSendArgsAndGetResult(),该方法主要做的事情是:将请求参数列表发送到zygote进程,并接收Zygote进程启动子进程的响应结果。
第二部分:
Zygote接收到AMS请求fork子进程过程
1:Zygote进程被init进程拉起后,会通过反射调用ZygotInit的main(),该方法主要做的事情是:
1.1:初始化ZygoteServer并创建服务端Socket用于接收、执行其它进程向Zygote进程发起的请求。
1.2:启动SystemServer进程。
1.3:最后调用runSelectLoop()开始循环接收其它进程发起的请求。
2:如果检测到有请求发过来,runSlectLoop()中会把一次Socket封装成ZygoteConnection,而后执行其runOnce()方法。
3:在runOnce()内部会调用Zygote.forkAndSpecialize():内部调用native方法进行实际的fork子进程操作。fork成功的话则子进程pid等于0,不为0则表示fork失败(fork()采用copy on write技术,这是linux创建进程的标准方法,调用一次,返回两次。)。
4:如果pid为0,则表示当前代码执行在子进程,需要执行handleChildProc(),该方法主要做的是:关闭与Zygote进程的Socket连接,执行ZygoteInit.zygoteInit()。
5:ZygoteInit.zygoteInit(),该方法主要执行"子进程"的运行时初始化操作(这些初始化包括:启动Binder线程池、创建VM、以及反射执行子进程ActivityThread线程等)。
5.1:RuntimeInit.commonInit():该方法用于执行一些“通用工作的初始化操作”(eg:设置异常捕获程序(Thread.setDefaultUncaughtExceptionHandler())、设置默认的UA(user agent等等))。
5.2:ZygoteInit.nativeZygoteInit():启动Binder线程池。
5.3:RuntimeInit.applicationInit():设置虚拟机参数,反射执行ActivityThread.main(),对main线程进行初始化。
详细过程
第一部分:AMS向Zygot进程发起启动app进程的请求
1.startSpecificActivityLocked()
总结
1:通过AMS.getProcessRecordLocked()根据“进程名、uid”查询是否App的进程启动了,如果进程未创建则返回null(ProcessRecord“用于记录app所运行在的进程的信息”)。
2:通过ActivityStack.setLaunchTime()记录下执行Activity启动操作的时间点。
3:App进程未启动,通过AMS.startProcessLocked()继续后续操作。
源码
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//App进程是否已经启动了
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//该时间被记录在ActivityStack中,记录何时执行“Activity的启动”操作的。
//在统计“冷启动耗时”与单个“Activity启动耗时”时会用到。
//见[小节1.2]
r.getStack().setLaunchTime(r);
//如果App进程已经启动了,则直接激活待启动Activity。
if (app != null && app.thread != null) {
try {
......
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
......
}
}
//App进程还没创建,则需要先创建App所运行在的进程
//见[小节1.3]
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
1.1.AMS.getProcessRecordLocked()
源码
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
//如果要查找的是系统进程
if (uid == SYSTEM_UID) {
......
}
ProcessRecord proc = mProcessNames.get(processName, uid);
......
return proc;
}
1.1.1:ProcessMap.get()
public E get(String name, int uid) {
SparseArray<E> uids = mMap.get(name);
//未缓存则返回null
if (uids == null) return null;
return uids.get(uid);
}
1.2.ActivityStack.setLaunchTime()
总结
1:记录下执行Activity启动操作的时间点。
2:在待启动Activity所在的视图树经过第一次解析、测量、布局、绘制之后会用到存储在ActivityStack中的这个时间点。具体的会在ActivityRecord.reportLaunchTimeLocked()借助此时间点来统计“当前Activity的启动耗时”。
源码
1.2.1:ActivityStack.setLaunchTime()
void setLaunchTime(ActivityRecord r) {
if (r.displayStartTime == 0) {
r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
if (mLaunchStartTime == 0) {
startLaunchTraces(r.packageName);
//记录执行Activity启动操作的时间点
mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
}
} else if (mLaunchStartTime == 0) {
startLaunchTraces(r.packageName);
//记录执行Activity启动操作的时间点
mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
}
}
1.2.2.ActivityRecord.reportLaunchTimeLocked()
源码
private void reportLaunchTimeLocked(final long curTime) {
......
final long thisTime = curTime - displayStartTime;
final long totalTime = stack.mLaunchStartTime != 0
? (curTime - stack.mLaunchStartTime) : thisTime;
if (SHOW_ACTIVITY_START_TIME) {
Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
userId, System.identityHashCode(this), shortComponentName,
thisTime, totalTime);
StringBuilder sb = service.mStringBuilder;
sb.setLength(0);
sb.append("Displayed ");
sb.append(shortComponentName);
sb.append(": ");
TimeUtils.formatDuration(thisTime, sb);
if (thisTime != totalTime) {
sb.append(" (total ");
TimeUtils.formatDuration(totalTime, sb);
sb.append(")");
}
Log.i(TAG, sb.toString());
}
.....
}
1.3.启动App进程
启动应用程序的进程主要分2个方面来分析:
1:AMS向Zygote发起fork子进程的过程。
2:Zygote接收AMS的请求创建子进程过程。
1.4.AMS向Zygote发起fork子进程的过程。
源码
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
1.5.AMS.startProcessLocked()
参数:
1:String processName:待启动的进程名。
2:ApplicationInfo info:存储的是Manifest文件中对<application>标签中声明的属性信息。
3:boolean knownToBeDead:此值为 true。
4:int intentFlags:此值为0。
5:String hostingType:此值为“activity”。用于表示“是因为执行什么操作才导致创建进程”的吗??
6:ComponentName hostingName:Intent 中保存的待启动Activity的组件信息。其中包括app的包名与待启动Activity的类名。
7:boolean allowWhileBooting:此值为 false。
8:boolean isolated:此值为 false。
9:int isolatedUid:此值为 0。
10:boolean keepIfLarge:此值为 true。
11:String abiOverride:此值为null。
12:String entryPoint:此值为null。
- entryPoint在启动 App 进程之前会被重新赋值为“ActivityThread的全限定名”。
- 在后续启动完进程后,会反射执行ActivityThread.main()开启ActivityThread表示的主线程并对其做相应初始化操作。
13:String[] entryPointArgs:此值为null。
14:Runnable crashHandler:此值为null。
总结
在启动App进程之前,需要先该把保存进程信息的ProcessRecord创建并缓存至AMS内部的ArrayMap中。
具体的:执行AMS. newProcessRecordLocked()先把保存待启动App进程的ProcessRecord创建完毕 并 缓存到AMS内部的一个ArrayMap。
源码
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;
//isolated为false,所以走这里
if (!isolated) {
//获取每个进程对应的ProcessRecord。
//因为待启动App还没有运行起来,所以获取的ProcessRecord为null。
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
......
} else {
app = null;
}
......
if (app == null) {
//先把ProcessRecord创建好,其次缓存至AMS服务中的“mProcessNames”属性指向的ProcessMap中( ProcessMap内部维护了一个ArrayMap来缓存已经启动完毕的进程信息)。
//见[小节1.6]
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
//如果创建失败,则退出此次启动进程操作,并返回null表示启动进程操作失败了。
return null;
}
......
} else {
......
}
//AMS服务已经在system_server进程中被初始化完毕了,mProcessesReady已经被赋值为了true。具体请查看`问题小节`。
//不会走这里
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
......
return app;
}
......
//见[小节1.7]
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
......
return (app.pid != 0) ? app : null;
}
1.6.AMS.newProcessRecordLocked()
总结:
1:创建保存进程信息的ProcessRecord。
2:调用AMS.addProcessNameLocked()把此ProcessRecord缓存起来。
源码
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
boolean isolated, int isolatedUid) {
String proc = customProcess != null ? customProcess : info.processName;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
final int userId = UserHandle.getUserId(info.uid);
int uid = info.uid;
if (isolated) {
......
}
//创建一个ProcessRecord
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
......
//见[小节1.6.1]
addProcessNameLocked(r);
return r;
1.6.1.AMS.addProcessNameLocked():把目标ProcessRecord缓存起来
private final void addProcessNameLocked(ProcessRecord proc) {
......
//把ProcessRecord缓存起来
mProcessNames.put(proc.processName, proc.uid, proc);
......
}
1.7.AMS.startProcessLocked()
总结
1:重新对entryPoint的内容赋值,赋值后它存储的是“ActivityThread类的全限定名”,ActivityThread在后续进程启动完毕后,系统会反射执行ActivityThread.main()开启ActivityThread表示的主线程并对其做相应初始化操作。
2:继续后续进程的创建操作。
3:创建进程的系统事件会被记录到trace中,方便采用trace工具获得此事件花费的时间。进程创建完毕后,还会输出相应信息至logcat。
4:进程创建完毕,保存进程信息至ProcessRecord(如更新进程id只ProcessRecord中)。
源码
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//App进程还未启动,此时pid为0。
if (app.pid > 0 && app.pid != MY_PID) {
......
}
......
try {
//设置该App是否可debug。
//应用进程是否可被调试,是由在Manifest文件注册Application时对<application>添加“android:debuggable”属性来支持的。true是可debug,false是不可以。
//在打debug包时,该属性是开启的。relase包是禁止的。
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
......
}
......
//因为entryPoint为null,所以isActivityProcess为true
boolean isActivityProcess = (entryPoint == null);
//因为entryPoint为null,所以为它赋值为“ActivityThread的全限定名”。
//entryPoint很重要,用于后续启动完进程后,开启ActivityThread表示的主线程。
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//各种系统trace信息,此时这里开始记录进程的创建事件
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
......
ProcessStartResult startResult;
//hostingType被初始化为“activity”,所以不会走这里。
if (hostingType.equals("webview_service")) {
......
} else {
//见[小节1.8]
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
//保存 创建进程所花费的时间。
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
......
//进程创建完毕后,会输出相应信息至logcat
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(startResult.pid);
buf.append(':');
buf.append(app.processName);
buf.append('/');
UserHandle.formatUid(buf, uid);
if (!isActivityProcess) {
buf.append(" [");
buf.append(entryPoint);
buf.append("]");
}
buf.append(" for ");
buf.append(hostingType);
if (hostingNameStr != null) {
buf.append(" ");
buf.append(hostingNameStr);
}
Slog.i(TAG, buf.toString());
//进程创建完毕,保存进程信息至ProcessRecord。
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
......
} catch (RuntimeException e) {
......
}
}
进程创建完毕log
04-25 16:40:20.824 1644-3146/? I/ActivityManager: Start proc 7880:sj.com.github_workspace/u0a83 for activity sj.com.github_workspace/.MainActivity
1.8.Process.start()
总结:
1:Process:用于管理操作系统进程的工具。
- 该类中定义了一些进程的uid。例如:系统uid包括 电话,wifi等进程。应用程序进程uid的取值范围(FIRST_APPLICATION_UID与LAST_APPLICATION_UID之间,也就是[10000,19999])。
- 提供了获取进程uid(应用id),userId(用户id),gid(进程组id),pid(进程id),ppid(父进程id)等信息的工具方法。(关于uid,userId,gid概念请参考 https://blog.csdn.net/zhanglianyu00/article/details/50253187)
2:Process类内部维护了一个ZygoteProcess类的实例,ZygoteProcess“用于保持与Zygote进程的通信状态。”
参数:
String processClass:ActivityThread类的全限定名。
String niceName:进程名。默认的话就是App的包名。
int uid:进程的uid。
int gid:进程组id。
int[] gids:待补充。。。
int debugFlags:存储了App进程是否可被debug的信息。
int mountExternal:待补充。。。
int targetSdkVersion:在Manifest文件中声明的targetSdk版本号。
String seInfo:待补充。。。
String abi:待补充。。。
String instructionSet:
String appDataDir:为存储App信息的内部存储目录(Sp文件、数据库就存在这里)。
String invokeWith:此值为null。
String[] extraArgs:此值为null。
源码
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 invokeWith,
String[] zygoteArgs) {
//见小节[1.9]
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
1.9.ZygoteProcess.start()
源码
public final Process.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 invokeWith,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
......
}
}
1.10.ZygoteProcess.startViaZygote()
private Process.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 invokeWith,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
// 设置一些运行时参数,这些参数就是根据传递给该方法的参数来设置的。
//例如设置把uid,gid这些信息都封装到argsForZygote 这个列表中。
......
synchronized(mLock) {
//见[小节1.11]与[小节1.12]
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
1.11.ZygoteProcess.openZygoteSocketIfNeeded()
总结:
1:该方法内部会通过ZygoteState.connect(),打开与Zygote进程之间的Socket连接.
2:ZygoteState:该类为ZygoteProcess的内部类。表示一次与Zygote进程建立的Socket通信过程。其内部维护了LocalSocket与Zygote进程进行通信。
1.12.ZygoteProcess.zygoteSendArgsAndGetResult()
总结
1:用于将请求参数列表发送到zygote进程,并接收Zygote进程启动子进程的响应结果。
2:Zygote会把fork子进程的pid返回给AMS 。(通过openZygoteSocketIfNeeded()建立好连接之后就需要向Zygote发送请求数据,以及响应 Zygote发回的响应数据。该方法就是用来做发送、接受上述事情的。)
源码
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// 检查参数列表
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;
//向Zygote进程写数据
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();
//等Zygote进程处理完毕后,读取Zygote进程的处理结果
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
//pid小于0则表示创建子进程失败的话,会抛出异常。
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
第二部分:Zygote接收到AMS请求fork子进程过程
前提:
Zygote进程被init进程拉起后,会通过反射调用ZygotInit的main()进行初始化操作。这些初始化操作主要包括:
1:初始化ZygoteServer并创建服务端Socket用于接收、执行其它进程向Zygote进程发起的请求。
2:启动SystemServer进程。
3:最后调用runSelectLoop()开始循环接收其它进程发起的请求。
关于Zygote进程的初始化操作,请参看<<Zygote进程启动过程学习与理解>>
接下来从Zygote接收来自运行在system_server进程的AMS发送的启动App进程请求的地方说起。
2.1.ZygoteServer.runSelectLoop():开启死循环接收来自其他进程发起的Socket请求。
源码
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
......
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
......
//开启死循环接收来自其他进程发起的Socket请求
while (true) {
......
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
......
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//如果接收到来自其他进程的Socket请求,则会走执行ZygoteConnection.run()
//见小节[2.2]
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
2.2.ZygoteConnection.runOnce():
总结:
1:fork函数,调用一次返回2次,在父进程返回子进程的实际pid,而在子进程中则返回0。这样做是为了“能够正确区分程序是运行在父进程还是子进程。”
2:调用Zygote.forkAndSpecialize()通过native方法创建子进程。
2:子进程启动完毕后,继续调用ZygoteConnection.handleChildProc()对子进程进行初始化。
源码
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
......
//pid默认为-1。
//AMS通过ZygoteProcess.zygoteSendArgsAndGetResult()向Zygote进程发送启动App进程的请求后,也会在该方法中进程的pid做检查,如果小于0,则会抛出“ZygoteStartFailedEx”提示创建进程失败。
int pid = -1;
......
//见小节[2.3]
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
} 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 {
//1:fork会“调用一次,返回两次”。分别在父进程、子进程返回。
//2:在父进程返回子进程的实际pid,而在子进程返回的pid为0。这样做是为了“能够正确区分程序是运行在父进程还是子进程。”
if (pid == 0) {
// 这是程序运行在新创建的子进程中
//fork()操作出的子进程是父进程的一个副本。父进程具备的他都用。自进程的虚拟地址空间与父进程一样,代码等都一致。那么Zygote进程内部开启了一个用于接收AMS发起的创建子进程的操作,该方法就是用来关闭“启动的用于接收AMS发起的Socket服务”。
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//见小节[2.4]
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
//这是运行在父进程
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
......
}
}
2.3.Zygote.forkAndSpecialize()
源码
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, String instructionSet, String appDataDir) {
......
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, instructionSet, appDataDir);
......
if (pid == 0) {
//采用trace记录fork子进程的后,执行“handleChildProc()”花费的时间
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
......
return pid;
}
2.4.ZygoteConnection.handleChildProc()(handle child process)
总结:
该方法在fork进程完毕后执行,用于关闭与Zygote进程的Socket连接, 执行ZygoteInit.zygoteInit()。
源码
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws Zygote.MethodAndArgsCaller {
//关闭与Zygote建立的Socket连接
closeSocket();
//结束对该方法的记录
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//这个invokeWidth从AMS向Zygote发起请求时指定的值就是null。
//不会走这里
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
//见小节[2.5]
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
2.5.ZygoteInit.zygoteInit()
总结:
1:通过RuntimeInit.commonInit()对一些运行时的公共数据进行初始化操作(eg:设置异常捕获程序(Thread.setDefaultUncaughtExceptionHandler())、设置默认的UA(user agent等等)。
2:通过ZygoteInit.nativeZygoteInit(),启动App进程的Binder线程池。
源码
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
//一些公共数据的初始化
//eg:设置异常捕获程序(Thread.setDefaultUncaughtExceptionHandler())、设置默认的UA(user agent等等)
RuntimeInit.commonInit();
//初始化App进程的Binder线程池
ZygoteInit.nativeZygoteInit();
//见小节[2.6]
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
2.6.ZygoteInit.applicationInit()
源码
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
//设置虚拟机参数
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
// 反射执行ActivityThread.main()
//见小节[2.7]
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
2.7.RuntimeInit.invokeStaticMain():反射执行ActivityThread.main(),对main线程进行初始化。
源码
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
......
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
.......
} catch (SecurityException ex) {
......
}
......
//见小节[2.8]
throw new Zygote.MethodAndArgsCaller(m, argv);
}
2.8.MethodAndArgsCaller .run():
总结
1:MethodAndArgsCaller是一个Runnable也是一个异常。该异常会在ZygiteInit.()中被捕获,捕获之后就会执行其run()。
2:在run()中,就是通过反射来执行ActivityThread.main()来对主线程进程初始化。
源码
public static class MethodAndArgsCaller extends Exception
implements Runnable {
......
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
......
} catch (InvocationTargetException ex) {
.....
}
}
}
问题:
1:AMS.mProcessesReady属性是什么意思?systemReady()方法又是干什么的?
此属性用于表示“一些初始化的流程是否准备完毕”。如果该值为 false,那么在创建进程时,可能“先不会走实际创建进程的操作”。为 true,则才会走继续通知Zygote进程fork子进程。
system_server被Zygote进程拉起后,会执行SystemServer.main()对system_server进程做初始化操作。其中像AMS、WMS 就是在其中初始化的,当初始化AMS后则会执行其systemReady()去做“一些准备工作”,等其内部相应准备工作准备好后,则会更新该值为 true。**
2:操作系统提供的fork()函数大概是怎么工作的?
1:fork()会“调用一次,返回两次”。分别在父进程、子进程返回。
2:在父进程返回子进程的实际pid,而在子进程返回的pid为0。这样做是为了“能够正确区分程序是运行在父进程还是子进程。
重要类说明
1:ProcessRecord:用于记录app进程信息。
2:Process:用于管理操作系统进程的工具。
该类中定义了一些进程的uid。例如:系统基础讷航uid包括 电话,wifi等进程。应用程序进程uid的取值范围(
FIRST_APPLICATION_UID与
LAST_APPLICATION_UID之间,也就是[10000,19999])。
提供了获取进程uid(用户id),gid(组id),pid(进程id),ppid(父进程id)等信息的工具方法。
该类内部维护了一个ZygoteProcess,用于通过ZygoteProcess.start()通知Zygote进程来启动app进程。
3:ZygoteProcess:用于保持与Zygote进程的通信状态。
4:ZygoteState:该类为ZygoteProcess的内部类。表示一次与Zygote进程建立的Socket通信过程。其内部维护了LocalSocket与Zygote进程进行通信。
5:ZygoteInit:init进程启动完Zygote 进程之后,会执行该类的main()去做一些其它事情。这些事情包括:
1:创建ZygoteServer用于接受AMS发起的创建应用进程请求。
2:启动SystemServer进程。
3:执行ZygoteServer.runSelectLoop()开始循环接收其它进程发起的请求。
ZygoteServer:为Zygote服务,用于接收并执行来自AMS向其发送的Socket请求。
ZygoteConnection:该类表示AMS向Zygote发起的一起Socket连接请求。
网友评论