考察內容:
- 瞭解Linux下進各啓動的方式
- 熟悉應用進程啓動的基本流程
- 深入理解應用進程啓動的原理
進程啓動方式
- 用fork()函數創建子進程後,在子進程的分支直接進入進程處理入口函數
- 在子進程的分支調用execvx(path) 啓動另一個可執行文件
應用進程啓動原理
- 什麼時候觸發的進程啓動?誰發起的?
- 進程是誰啓動的?怎麼啓動的?
什麼時候觸發的進程啓動?
在啓動組件的時候,如果發現組件所在的進程沒有啓動才發起進程啓動。
ProcessRecord app getESSRecordLocked(...);
if(app != null && app.thread != null){
//進程已經啓動了,這裏可以啓動組件了
return;
}
start.processName;
應用進程入口函數:
public static void main(String[] args){
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(flase); //內部將調用attachApplicationLocked()
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在啓動Service爲例:應用要啓動Service,這個請求會發到AMS,AMS最終會調用bringUpServiceLocked函數
String bringUpServiceLocked(ServiceRecord r, String procName,){
//根據進程名稱查找ProcessRecord
ProcessRecord app = mAm.getProcessRecordLocked(procName);
if(app != null && app.thread != null){
//進程已經啓動
realStartServiceLocked(r, app, execLnFg);
return null;
}
if(app == null){
//表示進程還沒啓動
app = mAm.startProcessLocked(procName, ...);
}
if(!mPendingServices.contains(r)){
//把要啓動的Service掛起,等進程啓動後再繼續,見attachApplicationLocked
mPendingServices.add(r);
}
return null;
}
boolean attachApplicationLocked(ProcessRecord proc, String processName){
if(mPendingServices.size() > 0){
ServiceRecord sr = null;
for(int i=0; i < mPendingServices.size(); i++){
sr = mPendingServices.get(i);
mPendingServices.remove(i);
i--;
realStartServiceLocked(sr, proc, sr.createdFromFg);
}
}
}
進程是怎麼啓動的?
啓動進程是在AMS中的startProcessLocked函數
- 打開本地socket (通過openZygoteSocketIfNeeded
- 發送參數列表 (zygoteSendArgsAndGetResult)
- 返回創建的進程ID
Zygote中的處理:
- 讀取socket發過來的參數列表
- 用這些參數創建進程
- 父進程通過socket把結果寫回去
- 子進程 執行一個Java類的入口函數,類名是AMS通過Socket發過來的,其實就是"ActivityThread"
課堂作業:
- 爲什麼是zygote來創建里程,是systemServer
- AMS和zygote爲什麼不用BInder通信?
迴歸:你知道應用進程是怎麼啓動的嗎?
- 應用進程是什麼時候啓動的?
- 由AMS向zygote發起的,通過socket通信
- zygote for出應用進程,執行ActivityThread的main函數
- 進程啓動之後向AMS報告,整個啓動纔算結束