目錄
- 概述
- 總結(jié)
- 詳細(xì)過(guò)程
- 問(wèn)題&主要類說(shuō)明
概述
-1-
在冷啟動(dòng)過(guò)程中,當(dāng)“為App啟動(dòng)做完準(zhǔn)備”之后( <<為目標(biāo)App啟動(dòng)做準(zhǔn)備>>)红淡,就需要檢查App進(jìn)程是否開(kāi)啟了卸伞,如果沒(méi)有則需要先執(zhí)行 App進(jìn)程的創(chuàng)建操作。
-2-
當(dāng)前源碼的分析是基于 Android8.0锉屈。
總結(jié)
應(yīng)用程序進(jìn)程的啟動(dòng)可以是分為2個(gè)部分的。
第一部分:
AMS向Zygote進(jìn)程發(fā)起啟動(dòng)app進(jìn)程的請(qǐng)求垮耳。
1:AMS調(diào)用其內(nèi)部的“startProcessLocked()”來(lái)開(kāi)啟啟動(dòng)app進(jìn)程的入口颈渊。該方法主要做的是:組裝發(fā)給zygote進(jìn)城的用于啟動(dòng)子進(jìn)程的參數(shù)列表(這些參數(shù)包括:uid,gid,entryPoint 參數(shù)等,entryPoint參數(shù)的值為ActivityThread的類全限定名终佛。該參數(shù)用于fork子進(jìn)程之后啟動(dòng)每個(gè)app進(jìn)程的ActivityThread去做初始化操作俊嗽。)
2:通過(guò)層層調(diào)用最終會(huì)執(zhí)行ZygoteProcess.startViaZygote(),該方法首先會(huì)把AMS服務(wù)傳過(guò)來(lái)的參數(shù)封裝到一個(gè)argsForZygote參數(shù)列表中铃彰。
3:調(diào)用ZygoteProcess內(nèi)部的openZygoteSocketIfNeeded()與Zygote進(jìn)程建立Socket連接绍豁。
4:調(diào)用ZygoteProcess的zygoteSendArgsAndGetResult(),該方法主要做的事情是:將請(qǐng)求參數(shù)列表發(fā)送到zygote進(jìn)程牙捉,并接收Z(yǔ)ygote進(jìn)程啟動(dòng)子進(jìn)程的響應(yīng)結(jié)果竹揍。
第二部分:
Zygote接收到AMS請(qǐng)求fork子進(jìn)程過(guò)程
1:Zygote進(jìn)程被init進(jìn)程拉起后,會(huì)通過(guò)反射調(diào)用ZygotInit的main()邪铲,該方法主要做的事情是:
1.1:初始化ZygoteServer并創(chuàng)建服務(wù)端Socket用于接收芬位、執(zhí)行其它進(jìn)程向Zygote進(jìn)程發(fā)起的請(qǐng)求。
1.2:?jiǎn)?dòng)SystemServer進(jìn)程带到。
1.3:最后調(diào)用runSelectLoop()開(kāi)始循環(huán)接收其它進(jìn)程發(fā)起的請(qǐng)求昧碉。
2:如果檢測(cè)到有請(qǐng)求發(fā)過(guò)來(lái),runSlectLoop()中會(huì)把一次Socket封裝成ZygoteConnection揽惹,而后執(zhí)行其runOnce()方法被饿。
3:在runOnce()內(nèi)部會(huì)調(diào)用Zygote.forkAndSpecialize():內(nèi)部調(diào)用native方法進(jìn)行實(shí)際的fork子進(jìn)程操作。fork成功的話則子進(jìn)程pid等于0,不為0則表示fork失敗(fork()采用copy on write技術(shù)搪搏,這是linux創(chuàng)建進(jìn)程的標(biāo)準(zhǔn)方法狭握,調(diào)用一次,返回兩次慕嚷。)哥牍。
4:如果pid為0,則表示當(dāng)前代碼執(zhí)行在子進(jìn)程喝检,需要執(zhí)行handleChildProc(),該方法主要做的是:關(guān)閉與Zygote進(jìn)程的Socket連接,執(zhí)行ZygoteInit.zygoteInit()嗅辣。
5:ZygoteInit.zygoteInit(),該方法主要執(zhí)行"子進(jìn)程"的運(yùn)行時(shí)初始化操作(這些初始化包括:啟動(dòng)Binder線程池、創(chuàng)建VM挠说、以及反射執(zhí)行子進(jìn)程ActivityThread線程等)澡谭。
5.1:RuntimeInit.commonInit():該方法用于執(zhí)行一些“通用工作的初始化操作”(eg:設(shè)置異常捕獲程序(Thread.setDefaultUncaughtExceptionHandler())、設(shè)置默認(rèn)的UA(user agent等等))。
5.2:ZygoteInit.nativeZygoteInit():?jiǎn)?dòng)Binder線程池蛙奖。
5.3:RuntimeInit.applicationInit():設(shè)置虛擬機(jī)參數(shù)潘酗,反射執(zhí)行ActivityThread.main(),對(duì)main線程進(jìn)行初始化雁仲。
詳細(xì)過(guò)程
第一部分:AMS向Zygot進(jìn)程發(fā)起啟動(dòng)app進(jìn)程的請(qǐng)求
1.startSpecificActivityLocked()
總結(jié)
1:通過(guò)AMS.getProcessRecordLocked()根據(jù)“進(jìn)程名仔夺、uid”查詢是否App的進(jìn)程啟動(dòng)了,如果進(jìn)程未創(chuàng)建則返回null(ProcessRecord“用于記錄app所運(yùn)行在的進(jìn)程的信息”)攒砖。
2:通過(guò)ActivityStack.setLaunchTime()記錄下執(zhí)行Activity啟動(dòng)操作的時(shí)間點(diǎn)缸兔。
3:App進(jìn)程未啟動(dòng),通過(guò)AMS.startProcessLocked()繼續(xù)后續(xù)操作吹艇。
源碼
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
//App進(jìn)程是否已經(jīng)啟動(dòng)了
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//該時(shí)間被記錄在ActivityStack中惰蜜,記錄何時(shí)執(zhí)行“Activity的啟動(dòng)”操作的。
//在統(tǒng)計(jì)“冷啟動(dòng)耗時(shí)”與單個(gè)“Activity啟動(dòng)耗時(shí)”時(shí)會(huì)用到受神。
//見(jiàn)[小節(jié)1.2]
r.getStack().setLaunchTime(r);
//如果App進(jìn)程已經(jīng)啟動(dòng)了抛猖,則直接激活待啟動(dòng)Activity。
if (app != null && app.thread != null) {
try {
......
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
......
}
}
//App進(jìn)程還沒(méi)創(chuàng)建鼻听,則需要先創(chuàng)建App所運(yùn)行在的進(jìn)程
//見(jiàn)[小節(jié)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) {
//如果要查找的是系統(tǒng)進(jìn)程
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()
總結(jié)
1:記錄下執(zhí)行Activity啟動(dòng)操作的時(shí)間點(diǎn)财著。
2:在待啟動(dòng)Activity所在的視圖樹(shù)經(jīng)過(guò)第一次解析、測(cè)量精算、布局瓢宦、繪制之后會(huì)用到存儲(chǔ)在ActivityStack中的這個(gè)時(shí)間點(diǎn)。具體的會(huì)在ActivityRecord.reportLaunchTimeLocked()借助此時(shí)間點(diǎn)來(lái)統(tǒng)計(jì)“當(dāng)前Activity的啟動(dòng)耗時(shí)”灰羽。
源碼
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);
//記錄執(zhí)行Activity啟動(dòng)操作的時(shí)間點(diǎn)
mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
}
} else if (mLaunchStartTime == 0) {
startLaunchTraces(r.packageName);
//記錄執(zhí)行Activity啟動(dòng)操作的時(shí)間點(diǎn)
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.啟動(dòng)App進(jìn)程
啟動(dòng)應(yīng)用程序的進(jìn)程主要分2個(gè)方面來(lái)分析:
1:AMS向Zygote發(fā)起fork子進(jìn)程的過(guò)程驮履。
2:Zygote接收AMS的請(qǐng)求創(chuàng)建子進(jìn)程過(guò)程。
1.4.AMS向Zygote發(fā)起fork子進(jìn)程的過(guò)程廉嚼。
源碼
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()
參數(shù):
1:String processName:待啟動(dòng)的進(jìn)程名玫镐。
2:ApplicationInfo info:存儲(chǔ)的是Manifest文件中對(duì)<application>標(biāo)簽中聲明的屬性信息。
3:boolean knownToBeDead:此值為 true怠噪。
4:int intentFlags:此值為0恐似。
5:String hostingType:此值為“activity”。用于表示“是因?yàn)閳?zhí)行什么操作才導(dǎo)致創(chuàng)建進(jìn)程”的嗎傍念?矫夷?
6:ComponentName hostingName:Intent 中保存的待啟動(dòng)Activity的組件信息。其中包括app的包名與待啟動(dòng)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在啟動(dòng) App 進(jìn)程之前會(huì)被重新賦值為“ActivityThread的全限定名”嘶摊。
- 在后續(xù)啟動(dòng)完進(jìn)程后延蟹,會(huì)反射執(zhí)行ActivityThread.main()開(kāi)啟ActivityThread表示的主線程并對(duì)其做相應(yīng)初始化操作。
13:String[] entryPointArgs:此值為null叶堆。
14:Runnable crashHandler:此值為null阱飘。
總結(jié)
在啟動(dòng)App進(jìn)程之前,需要先該把保存進(jìn)程信息的ProcessRecord創(chuàng)建并緩存至AMS內(nèi)部的ArrayMap中虱颗。
具體的:執(zhí)行AMS. newProcessRecordLocked()先把保存待啟動(dòng)App進(jìn)程的ProcessRecord創(chuàng)建完畢 并 緩存到AMS內(nèi)部的一個(gè)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) {
//獲取每個(gè)進(jìn)程對(duì)應(yīng)的ProcessRecord上枕。
//因?yàn)榇龁?dòng)App還沒(méi)有運(yùn)行起來(lái),所以獲取的ProcessRecord為null弱恒。
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
......
} else {
app = null;
}
......
if (app == null) {
//先把ProcessRecord創(chuàng)建好辨萍,其次緩存至AMS服務(wù)中的“mProcessNames”屬性指向的ProcessMap中( ProcessMap內(nèi)部維護(hù)了一個(gè)ArrayMap來(lái)緩存已經(jīng)啟動(dòng)完畢的進(jìn)程信息)。
//見(jiàn)[小節(jié)1.6]
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
//如果創(chuàng)建失敗返弹,則退出此次啟動(dòng)進(jìn)程操作锈玉,并返回null表示啟動(dòng)進(jìn)程操作失敗了。
return null;
}
......
} else {
......
}
//AMS服務(wù)已經(jīng)在system_server進(jìn)程中被初始化完畢了义起,mProcessesReady已經(jīng)被賦值為了true裁替。具體請(qǐng)查看`問(wèn)題小節(jié)`毛俏。
//不會(huì)走這里
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
......
return app;
}
......
//見(jiàn)[小節(jié)1.7]
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
......
return (app.pid != 0) ? app : null;
}
1.6.AMS.newProcessRecordLocked()
總結(jié):
1:創(chuàng)建保存進(jìn)程信息的ProcessRecord。
2:調(diào)用AMS.addProcessNameLocked()把此ProcessRecord緩存起來(lái)。
源碼
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) {
......
}
//創(chuàng)建一個(gè)ProcessRecord
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
......
//見(jiàn)[小節(jié)1.6.1]
addProcessNameLocked(r);
return r;
1.6.1.AMS.addProcessNameLocked():把目標(biāo)ProcessRecord緩存起來(lái)
private final void addProcessNameLocked(ProcessRecord proc) {
......
//把ProcessRecord緩存起來(lái)
mProcessNames.put(proc.processName, proc.uid, proc);
......
}
1.7.AMS.startProcessLocked()
總結(jié)
1:重新對(duì)entryPoint的內(nèi)容賦值固灵,賦值后它存儲(chǔ)的是“ActivityThread類的全限定名”,ActivityThread在后續(xù)進(jìn)程啟動(dòng)完畢后杠巡,系統(tǒng)會(huì)反射執(zhí)行ActivityThread.main()開(kāi)啟ActivityThread表示的主線程并對(duì)其做相應(yīng)初始化操作派歌。
2:繼續(xù)后續(xù)進(jìn)程的創(chuàng)建操作。
3:創(chuàng)建進(jìn)程的系統(tǒng)事件會(huì)被記錄到trace中含滴,方便采用trace工具獲得此事件花費(fèi)的時(shí)間诱渤。進(jìn)程創(chuàng)建完畢后,還會(huì)輸出相應(yīng)信息至logcat谈况。
4:進(jìn)程創(chuàng)建完畢勺美,保存進(jìn)程信息至ProcessRecord(如更新進(jìn)程id只ProcessRecord中)。
源碼
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
//App進(jìn)程還未啟動(dòng)碑韵,此時(shí)pid為0赡茸。
if (app.pid > 0 && app.pid != MY_PID) {
......
}
......
try {
//設(shè)置該App是否可debug。
//應(yīng)用進(jìn)程是否可被調(diào)試泼诱,是由在Manifest文件注冊(cè)Application時(shí)對(duì)<application>添加“android:debuggable”屬性來(lái)支持的坛掠。true是可debug,false是不可以。
//在打debug包時(shí)屉栓,該屬性是開(kāi)啟的舷蒲。relase包是禁止的。
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
......
}
......
//因?yàn)閑ntryPoint為null友多,所以isActivityProcess為true
boolean isActivityProcess = (entryPoint == null);
//因?yàn)閑ntryPoint為null牲平,所以為它賦值為“ActivityThread的全限定名”。
//entryPoint很重要域滥,用于后續(xù)啟動(dòng)完進(jìn)程后纵柿,開(kāi)啟ActivityThread表示的主線程。
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//各種系統(tǒng)trace信息启绰,此時(shí)這里開(kāi)始記錄進(jìn)程的創(chuàng)建事件
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
......
ProcessStartResult startResult;
//hostingType被初始化為“activity”昂儒,所以不會(huì)走這里。
if (hostingType.equals("webview_service")) {
......
} else {
//見(jiàn)[小節(jié)1.8]
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
//保存 創(chuàng)建進(jìn)程所花費(fèi)的時(shí)間委可。
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
......
//進(jìn)程創(chuàng)建完畢后渊跋,會(huì)輸出相應(yīng)信息至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());
//進(jìn)程創(chuàng)建完畢,保存進(jìn)程信息至ProcessRecord着倾。
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
......
} catch (RuntimeException e) {
......
}
}
進(jìn)程創(chuàng)建完畢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()
總結(jié):
1:Process:用于管理操作系統(tǒng)進(jìn)程的工具拾酝。
- 該類中定義了一些進(jìn)程的uid。例如:系統(tǒng)uid包括 電話,wifi等進(jìn)程卡者。應(yīng)用程序進(jìn)程uid的取值范圍(FIRST_APPLICATION_UID與LAST_APPLICATION_UID之間,也就是[10000,19999])蒿囤。
- 提供了獲取進(jìn)程uid(應(yīng)用id),userId(用戶id),gid(進(jìn)程組id),pid(進(jìn)程id),ppid(父進(jìn)程id)等信息的工具方法。(關(guān)于uid,userId,gid概念請(qǐng)參考 https://blog.csdn.net/zhanglianyu00/article/details/50253187)
2:Process類內(nèi)部維護(hù)了一個(gè)ZygoteProcess類的實(shí)例崇决,ZygoteProcess“用于保持與Zygote進(jìn)程的通信狀態(tài)材诽。”
參數(shù):
String processClass:ActivityThread類的全限定名恒傻。
String niceName:進(jìn)程名岳守。默認(rèn)的話就是App的包名。
int uid:進(jìn)程的uid碌冶。
int gid:進(jìn)程組id湿痢。
int[] gids:待補(bǔ)充。扑庞。譬重。
int debugFlags:存儲(chǔ)了App進(jìn)程是否可被debug的信息。
int mountExternal:待補(bǔ)充罐氨。臀规。。
int targetSdkVersion:在Manifest文件中聲明的targetSdk版本號(hào)栅隐。
String seInfo:待補(bǔ)充塔嬉。玩徊。。
String abi:待補(bǔ)充谨究。恩袱。。
String instructionSet:
String appDataDir:為存儲(chǔ)App信息的內(nèi)部存儲(chǔ)目錄(Sp文件胶哲、數(shù)據(jù)庫(kù)就存在這里)畔塔。
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) {
//見(jiàn)小節(jié)[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>();
// 設(shè)置一些運(yùn)行時(shí)參數(shù)澈吨,這些參數(shù)就是根據(jù)傳遞給該方法的參數(shù)來(lái)設(shè)置的。
//例如設(shè)置把uid,gid這些信息都封裝到argsForZygote 這個(gè)列表中寄摆。
......
synchronized(mLock) {
//見(jiàn)[小節(jié)1.11]與[小節(jié)1.12]
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
1.11.ZygoteProcess.openZygoteSocketIfNeeded()
總結(jié):
1:該方法內(nèi)部會(huì)通過(guò)ZygoteState.connect(),打開(kāi)與Zygote進(jìn)程之間的Socket連接.
2:ZygoteState:該類為ZygoteProcess的內(nèi)部類谅辣。表示一次與Zygote進(jìn)程建立的Socket通信過(guò)程。其內(nèi)部維護(hù)了LocalSocket與Zygote進(jìn)程進(jìn)行通信婶恼。
1.12.ZygoteProcess.zygoteSendArgsAndGetResult()
總結(jié)
1:用于將請(qǐng)求參數(shù)列表發(fā)送到zygote進(jìn)程屈藐,并接收Z(yǔ)ygote進(jìn)程啟動(dòng)子進(jìn)程的響應(yīng)結(jié)果。
2:Zygote會(huì)把fork子進(jìn)程的pid返回給AMS 熙尉。(通過(guò)openZygoteSocketIfNeeded()建立好連接之后就需要向Zygote發(fā)送請(qǐng)求數(shù)據(jù),以及響應(yīng) Zygote發(fā)回的響應(yīng)數(shù)據(jù)搓扯。該方法就是用來(lái)做發(fā)送检痰、接受上述事情的。)
源碼
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// 檢查參數(shù)列表
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進(jìn)程寫數(shù)據(jù)
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進(jìn)程處理完畢后锨推,讀取Zygote進(jìn)程的處理結(jié)果
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
//pid小于0則表示創(chuàng)建子進(jìn)程失敗的話铅歼,會(huì)拋出異常。
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
第二部分:Zygote接收到AMS請(qǐng)求fork子進(jìn)程過(guò)程
前提:
Zygote進(jìn)程被init進(jìn)程拉起后换可,會(huì)通過(guò)反射調(diào)用ZygotInit的main()進(jìn)行初始化操作椎椰。這些初始化操作主要包括:
1:初始化ZygoteServer并創(chuàng)建服務(wù)端Socket用于接收、執(zhí)行其它進(jìn)程向Zygote進(jìn)程發(fā)起的請(qǐng)求沾鳄。
2:?jiǎn)?dòng)SystemServer進(jìn)程慨飘。
3:最后調(diào)用runSelectLoop()開(kāi)始循環(huán)接收其它進(jìn)程發(fā)起的請(qǐng)求。
關(guān)于Zygote進(jìn)程的初始化操作译荞,請(qǐng)參看<<Zygote進(jìn)程啟動(dòng)過(guò)程學(xué)習(xí)與理解>>
接下來(lái)從Zygote接收來(lái)自運(yùn)行在system_server進(jìn)程的AMS發(fā)送的啟動(dòng)App進(jìn)程請(qǐng)求的地方說(shuō)起瓤的。
2.1.ZygoteServer.runSelectLoop():開(kāi)啟死循環(huán)接收來(lái)自其他進(jìn)程發(fā)起的Socket請(qǐng)求。
源碼
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
......
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
......
//開(kāi)啟死循環(huán)接收來(lái)自其他進(jìn)程發(fā)起的Socket請(qǐng)求
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 {
//如果接收到來(lái)自其他進(jìn)程的Socket請(qǐng)求吞歼,則會(huì)走執(zhí)行ZygoteConnection.run()
//見(jiàn)小節(jié)[2.2]
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
2.2.ZygoteConnection.runOnce():
總結(jié):
1:fork函數(shù)圈膏,調(diào)用一次返回2次,在父進(jìn)程返回子進(jìn)程的實(shí)際pid篙骡,而在子進(jìn)程中則返回0稽坤。這樣做是為了“能夠正確區(qū)分程序是運(yùn)行在父進(jìn)程還是子進(jìn)程丈甸。”
2:調(diào)用Zygote.forkAndSpecialize()通過(guò)native方法創(chuàng)建子進(jìn)程尿褪。
2:子進(jìn)程啟動(dòng)完畢后睦擂,繼續(xù)調(diào)用ZygoteConnection.handleChildProc()對(duì)子進(jìn)程進(jìn)行初始化。
源碼
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
......
//pid默認(rèn)為-1茫多。
//AMS通過(guò)ZygoteProcess.zygoteSendArgsAndGetResult()向Zygote進(jìn)程發(fā)送啟動(dòng)App進(jìn)程的請(qǐng)求后祈匙,也會(huì)在該方法中進(jìn)程的pid做檢查,如果小于0天揖,則會(huì)拋出“ZygoteStartFailedEx”提示創(chuàng)建進(jìn)程失敗夺欲。
int pid = -1;
......
//見(jiàn)小節(jié)[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會(huì)“調(diào)用一次,返回兩次”今膊。分別在父進(jìn)程些阅、子進(jìn)程返回。
//2:在父進(jìn)程返回子進(jìn)程的實(shí)際pid斑唬,而在子進(jìn)程返回的pid為0市埋。這樣做是為了“能夠正確區(qū)分程序是運(yùn)行在父進(jìn)程還是子進(jìn)程∷×酰”
if (pid == 0) {
// 這是程序運(yùn)行在新創(chuàng)建的子進(jìn)程中
//fork()操作出的子進(jìn)程是父進(jìn)程的一個(gè)副本缤谎。父進(jìn)程具備的他都用。自進(jìn)程的虛擬地址空間與父進(jìn)程一樣褐着,代碼等都一致坷澡。那么Zygote進(jìn)程內(nèi)部開(kāi)啟了一個(gè)用于接收AMS發(fā)起的創(chuàng)建子進(jìn)程的操作,該方法就是用來(lái)關(guān)閉“啟動(dòng)的用于接收AMS發(fā)起的Socket服務(wù)”含蓉。
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//見(jiàn)小節(jié)[2.4]
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
//這是運(yùn)行在父進(jìn)程
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子進(jìn)程的后频敛,執(zhí)行“handleChildProc()”花費(fèi)的時(shí)間
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
......
return pid;
}
2.4.ZygoteConnection.handleChildProc()(handle child process)
總結(jié):
該方法在fork進(jìn)程完畢后執(zhí)行,用于關(guān)閉與Zygote進(jìn)程的Socket連接馅扣, 執(zhí)行ZygoteInit.zygoteInit()斟赚。
源碼
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws Zygote.MethodAndArgsCaller {
//關(guān)閉與Zygote建立的Socket連接
closeSocket();
//結(jié)束對(duì)該方法的記錄
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//這個(gè)invokeWidth從AMS向Zygote發(fā)起請(qǐng)求時(shí)指定的值就是null。
//不會(huì)走這里
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
} else {
//見(jiàn)小節(jié)[2.5]
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
2.5.ZygoteInit.zygoteInit()
總結(jié):
1:通過(guò)RuntimeInit.commonInit()對(duì)一些運(yùn)行時(shí)的公共數(shù)據(jù)進(jìn)行初始化操作(eg:設(shè)置異常捕獲程序(Thread.setDefaultUncaughtExceptionHandler())差油、設(shè)置默認(rèn)的UA(user agent等等)拗军。
2:通過(guò)ZygoteInit.nativeZygoteInit(),啟動(dòng)App進(jìn)程的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();
//一些公共數(shù)據(jù)的初始化
//eg:設(shè)置異常捕獲程序(Thread.setDefaultUncaughtExceptionHandler())食绿、設(shè)置默認(rèn)的UA(user agent等等)
RuntimeInit.commonInit();
//初始化App進(jìn)程的Binder線程池
ZygoteInit.nativeZygoteInit();
//見(jiàn)小節(jié)[2.6]
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
2.6.ZygoteInit.applicationInit()
源碼
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
//設(shè)置虛擬機(jī)參數(shù)
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
// 反射執(zhí)行ActivityThread.main()
//見(jiàn)小節(jié)[2.7]
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
2.7.RuntimeInit.invokeStaticMain():反射執(zhí)行ActivityThread.main(),對(duì)main線程進(jìn)行初始化公罕。
源碼
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) {
......
}
......
//見(jiàn)小節(jié)[2.8]
throw new Zygote.MethodAndArgsCaller(m, argv);
}
2.8.MethodAndArgsCaller .run():
總結(jié)
1:MethodAndArgsCaller是一個(gè)Runnable也是一個(gè)異常器紧。該異常會(huì)在ZygiteInit.()中被捕獲,捕獲之后就會(huì)執(zhí)行其run()楼眷。
2:在run()中铲汪,就是通過(guò)反射來(lái)執(zhí)行ActivityThread.main()來(lái)對(duì)主線程進(jìn)程初始化熊尉。
源碼
public static class MethodAndArgsCaller extends Exception
implements Runnable {
......
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
......
} catch (InvocationTargetException ex) {
.....
}
}
}
問(wèn)題:
1:AMS.mProcessesReady屬性是什么意思?systemReady()方法又是干什么的掌腰?
此屬性用于表示“一些初始化的流程是否準(zhǔn)備完畢”狰住。如果該值為 false,那么在創(chuàng)建進(jìn)程時(shí)齿梁,可能“先不會(huì)走實(shí)際創(chuàng)建進(jìn)程的操作”催植。為 true,則才會(huì)走繼續(xù)通知Zygote進(jìn)程fork子進(jìn)程勺择。
system_server被Zygote進(jìn)程拉起后创南,會(huì)執(zhí)行SystemServer.main()對(duì)system_server進(jìn)程做初始化操作。其中像AMS省核、WMS 就是在其中初始化的稿辙,當(dāng)初始化AMS后則會(huì)執(zhí)行其systemReady()去做“一些準(zhǔn)備工作”,等其內(nèi)部相應(yīng)準(zhǔn)備工作準(zhǔn)備好后气忠,則會(huì)更新該值為 true邻储。**
2:操作系統(tǒng)提供的fork()函數(shù)大概是怎么工作的?
1:fork()會(huì)“調(diào)用一次旧噪,返回兩次”吨娜。分別在父進(jìn)程、子進(jìn)程返回淘钟。
2:在父進(jìn)程返回子進(jìn)程的實(shí)際pid宦赠,而在子進(jìn)程返回的pid為0。這樣做是為了“能夠正確區(qū)分程序是運(yùn)行在父進(jìn)程還是子進(jìn)程日月。
重要類說(shuō)明
1:ProcessRecord:用于記錄app進(jìn)程信息。
2:Process:用于管理操作系統(tǒng)進(jìn)程的工具缤骨。
該類中定義了一些進(jìn)程的uid爱咬。例如:系統(tǒng)基礎(chǔ)訥航uid包括 電話,wifi等進(jìn)程。應(yīng)用程序進(jìn)程uid的取值范圍(
FIRST_APPLICATION_UID與
LAST_APPLICATION_UID之間,也就是[10000,19999])绊起。
提供了獲取進(jìn)程uid(用戶id),gid(組id),pid(進(jìn)程id),ppid(父進(jìn)程id)等信息的工具方法精拟。
該類內(nèi)部維護(hù)了一個(gè)ZygoteProcess虱歪,用于通過(guò)ZygoteProcess.start()通知Zygote進(jìn)程來(lái)啟動(dòng)app進(jìn)程蜂绎。
3:ZygoteProcess:用于保持與Zygote進(jìn)程的通信狀態(tài)。
4:ZygoteState:該類為ZygoteProcess的內(nèi)部類笋鄙。表示一次與Zygote進(jìn)程建立的Socket通信過(guò)程师枣。其內(nèi)部維護(hù)了LocalSocket與Zygote進(jìn)程進(jìn)行通信。
5:ZygoteInit:init進(jìn)程啟動(dòng)完Zygote 進(jìn)程之后萧落,會(huì)執(zhí)行該類的main()去做一些其它事情践美。這些事情包括:
1:創(chuàng)建ZygoteServer用于接受AMS發(fā)起的創(chuàng)建應(yīng)用進(jìn)程請(qǐng)求洗贰。
2:?jiǎn)?dòng)SystemServer進(jìn)程。
3:執(zhí)行ZygoteServer.runSelectLoop()開(kāi)始循環(huán)接收其它進(jìn)程發(fā)起的請(qǐng)求陨倡。
ZygoteServer:為Zygote服務(wù)敛滋,用于接收并執(zhí)行來(lái)自AMS向其發(fā)送的Socket請(qǐng)求。
ZygoteConnection:該類表示AMS向Zygote發(fā)起的一起Socket連接請(qǐng)求兴革。