Android系統(tǒng)中的進(jìn)程管理:進(jìn)程的創(chuàng)建
對(duì)于操作系統(tǒng)來說,進(jìn)程管理是其最重要的職責(zé)之一。
考慮到這部分的內(nèi)容較多,因此會(huì)拆分成幾篇文章來講解。
本文是進(jìn)程管理系統(tǒng)文章的***篇,會(huì)講解Android系統(tǒng)中的進(jìn)程創(chuàng)建。
本文適合Android平臺(tái)的應(yīng)用程序開發(fā)者,也適合對(duì)于Android系統(tǒng)內(nèi)部實(shí)現(xiàn)感興趣的讀者。
概述
Android系統(tǒng)以Linux內(nèi)核為基礎(chǔ),所以對(duì)于進(jìn)程的管理自然離不開Linux本身提供的機(jī)制。例如:
- 通過fork來創(chuàng)建進(jìn)行
- 通過信號(hào)量來管理進(jìn)程
- 通過proc文件系統(tǒng)來查詢和調(diào)整進(jìn)程狀態(tài)等
對(duì)于Android來說,進(jìn)程管理的主要內(nèi)容包括以下幾個(gè)部分內(nèi)容:
- 進(jìn)程的創(chuàng)建
- 進(jìn)程的優(yōu)先級(jí)管理
- 進(jìn)程的內(nèi)存管理
- 進(jìn)程的回收和死亡處理
本文會(huì)專門講解進(jìn)程的創(chuàng)建,其余部分將在后面的文章中講解。
主要模塊
為了便于下文的講解,這里先介紹一下Android系統(tǒng)中牽涉到進(jìn)程創(chuàng)建的幾個(gè)主要模塊。
同時(shí)為了便于讀者更詳細(xì)的了解這些模塊,這里也同時(shí)提供了這些模塊的代碼路徑。
這里提到的代碼路徑是指AOSP的源碼數(shù)中的路徑。
關(guān)于如何獲取AOSP源碼請(qǐng)參見這里:Downloading the Source。
本文以Android N版本的代碼為示例,所用到的Source Code Tags是:android-7.0.0_r1。
相關(guān)模塊:
- app_process
代碼路徑:frameworks/base/cmds/app_process
說明:app_process是一個(gè)可執(zhí)行程序,該程序的主要作用是啟動(dòng)zygote和system_server進(jìn)程。
- Zygote
代碼路徑:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
說明:zygote進(jìn)程是所有應(yīng)用進(jìn)程的父進(jìn)程,這是系統(tǒng)中一個(gè)非常重要的進(jìn)程,下文我們會(huì)詳細(xì)講解。
- ActivityManager
代碼路徑:frameworks/base/services/core/java/com/android/server/am/
說明:am是ActivityManager的縮寫。
這個(gè)目錄下的代碼負(fù)責(zé)了Android全部四大組件(Activity,Service,ContentProvider,BroadcastReceiver)的管理,并且還掌控了所有應(yīng)用程序進(jìn)程的創(chuàng)建和進(jìn)程的優(yōu)先級(jí)管理。
因此,這個(gè)部分的內(nèi)容將是本系列文章講解的重點(diǎn)。
進(jìn)程與線程
Android官方開發(fā)網(wǎng)站的這篇文章:Processes and Threads 非常好的介紹了Android系統(tǒng)中進(jìn)程相關(guān)的一些基本概念和重要知識(shí)。
在閱讀下文之前,請(qǐng)務(wù)必將這篇文章瀏覽一遍。
關(guān)于進(jìn)程
在Android系統(tǒng)中,進(jìn)程可以大致分為系統(tǒng)進(jìn)程和應(yīng)用進(jìn)程兩大類。
系統(tǒng)進(jìn)程是系統(tǒng)內(nèi)置的(例如:init,zygote,system_server進(jìn)程),屬于操作系統(tǒng)必不可少的一部分。系統(tǒng)進(jìn)程的作用在于:
- 管理硬件設(shè)備
- 提供訪問設(shè)備的基本能力
- 管理應(yīng)用進(jìn)程
應(yīng)用進(jìn)程是指應(yīng)用程序運(yùn)行的進(jìn)程。這些應(yīng)用程序可能是系統(tǒng)出廠自帶的(例如Launcher,電話,短信等應(yīng)用),也可能是用戶自己安裝的(例如:微信,支付寶等)。
系統(tǒng)進(jìn)程的數(shù)量通常是固定的(出廠或者系統(tǒng)升級(jí)之后就確定了),并且系統(tǒng)進(jìn)程通常是一直存活,常駐內(nèi)存的。系統(tǒng)進(jìn)程的異常退出將可能導(dǎo)致設(shè)備無法正常使用。
而應(yīng)用程序和應(yīng)用進(jìn)程在每個(gè)人使用的設(shè)備上通常是各不一樣的。如何管理好這些不確定的應(yīng)用進(jìn)程,就是操作系統(tǒng)本身要仔細(xì)考慮的內(nèi)容。也是衡量一個(gè)操作系統(tǒng)好壞的標(biāo)準(zhǔn)之一。
在本文中,我們會(huì)介紹init,zygote和system_server三個(gè)系統(tǒng)進(jìn)程。
除此之外,本系列文章將會(huì)把主要精力集中在講解Android系統(tǒng)如何管理應(yīng)用進(jìn)程上。
init進(jìn)程
init進(jìn)程是一切的開始,在Android系統(tǒng)中,所有進(jìn)程的進(jìn)程號(hào)都是不確定的,唯獨(dú)init進(jìn)程的進(jìn)程號(hào)一定是1。
因?yàn)檫@個(gè)進(jìn)程一定是系統(tǒng)起來的***個(gè)進(jìn)程。并且,init進(jìn)程掌控了整個(gè)系統(tǒng)的啟動(dòng)邏輯。
我們知道,Android可能運(yùn)行在各種不同的平臺(tái),不同的設(shè)備上。因此,啟動(dòng)的邏輯是不盡相同的。
為了適應(yīng)各種平臺(tái)和設(shè)備的需求,init進(jìn)程的初始化工作通過init.rc配置文件來管理。
你可以在AOSP源碼的system/core/rootdir/路徑找到這些配置文件。
配置文件的主入口文件是init.rc,這個(gè)文件會(huì)通過import引入其他幾個(gè)文件。
在本文中,我們統(tǒng)稱這些文件為init.rc。
init.rc通過Android Init Language來進(jìn)行配置。
建議讀者大致閱讀一下其 語法說明 。
init.rc中配置了系統(tǒng)啟動(dòng)的時(shí)候該做哪些事情,以及啟動(dòng)哪些系統(tǒng)進(jìn)程。
這其中有兩個(gè)特別重要的進(jìn)程就是:zygote和system_server進(jìn)程。
- zygote的中文意思是“受精卵“。這是一個(gè)很有寓意的名稱:所有的應(yīng)用進(jìn)程都是由zygote fork出來的子進(jìn)程,因此zygote進(jìn)程是所有應(yīng)用進(jìn)程的父進(jìn)程。
- system_server 這個(gè)進(jìn)程正如其名稱一樣,這是一個(gè)系統(tǒng)服務(wù)器。Framework層的幾乎所有服務(wù)都位于這個(gè)進(jìn)程中。這其中就包括管理四大組件的ActivityManagerService。
Zygote進(jìn)程
init.rc文件會(huì)根據(jù)平臺(tái)不一樣,選擇下面幾個(gè)文件中的一個(gè)來啟動(dòng)zygote進(jìn)程:
- init.zygote32.rc
- init.zygote32_64.rc
- init.zygote64.rc
- init.zygote64_32.rc
這幾個(gè)文件的內(nèi)容是大致一致的,僅僅是為了不同平臺(tái)服務(wù)的。這里我們以init.zygote32.rc的文件為例,來看看其中的內(nèi)容:
- service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
- class main
- socket zygote stream 660 root system
- onrestart write /sys/android_power/request_state wake
- onrestart write /sys/power/state on
- onrestart restart audioserver
- onrestart restart cameraserver
- onrestart restart media
- onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
在這段配置文件中(如果你不明白這段配置的含義,請(qǐng)閱讀一下文檔:Android Init Language),啟動(dòng)了一個(gè)名稱叫做zygote的服務(wù)進(jìn)程。這個(gè)進(jìn)程是通過/system/bin/app_process 這個(gè)可執(zhí)行程序創(chuàng)建的。
并且在啟動(dòng)這個(gè)可執(zhí)行程序的時(shí)候,傳遞了`-Xzygote /system/bin --zygote --start-system-server
class main` 這些參數(shù)。
要知道這里到底做了什么,我們需要看一下app_process的源碼。
app_process的源碼在這個(gè)路徑:frameworks/base/cmds/app_process/app_main.cpp。
這個(gè)文件的main函數(shù)的有如下代碼:
- int main(int argc, char* const argv[])
- {
- ...
- while (i < argc) {
- const char* arg = argv[i++];
- if (strcmp(arg, "--zygote") == 0) {
- zygote = true;
- niceName = ZYGOTE_NICE_NAME;
- } else if (strcmp(arg, "--start-system-server") == 0) {
- startSystemServer = true;
- ...
- }
- ...
- if (!className.isEmpty()) {
- ...
- } else {
- ...
- if (startSystemServer) {
- args.add(String8("start-system-server"));
- }
- }
- ...
- if (zygote) {
- runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
- } else if (className) {
- runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
- } else {
- fprintf(stderr, "Error: no class name or --zygote supplied.\n");
- app_usage();
- LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
- return 10;
- }
- }
這里會(huì)判斷,
- 如果執(zhí)行這個(gè)命令時(shí)帶了--zygote參數(shù),就會(huì)通過runtime.start啟動(dòng)com.android.internal.os.ZygoteInit。
- 如果參數(shù)中帶有--start-system-server參數(shù),就會(huì)將start-system-server添加到args中。
這段代碼是C++實(shí)現(xiàn)的。在執(zhí)行這段代碼的時(shí)候還沒有任何Java的環(huán)境。而runtime.start就是啟動(dòng)Java虛擬機(jī),并在虛擬機(jī)中啟動(dòng)指定的類。于是接下來的邏輯就在ZygoteInit.java中了。
這個(gè)文件的main函數(shù)主要代碼如下:
- public static void main(String argv[]) {
- ...
- try {
- ...
- 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)) {
- ...
- }
- }
- ...
- registerZygoteSocket(socketName);
- ...
- preload();
- ...
- Zygote.nativeUnmountStorageOnInit();
- ZygoteHooks.stopZygoteNoThreadCreation();
- if (startSystemServer) {
- startSystemServer(abiList, socketName);
- }
- Log.i(TAG, "Accepting command socket connections");
- runSelectLoop(abiList);
- closeServerSocket();
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- Log.e(TAG, "Zygote died with exception", ex);
- closeServerSocket();
- throw ex;
- }
- }
在這段代碼中,我們主要關(guān)注如下幾行:
- 通過 registerZygoteSocket(socketName); 注冊(cè)Zygote Socket
- 通過 preload(); 預(yù)先加載所有應(yīng)用都需要的公共資源
- 通過 startSystemServer(abiList, socketName); 啟動(dòng)system_server
- 通過 runSelectLoop(abiList); 在Looper上等待連接
這里需要說明的是:zygote進(jìn)程啟動(dòng)之后,會(huì)啟動(dòng)一個(gè)socket套接字,并通過Looper一直在這個(gè)套接字上等待連接。
所有應(yīng)用進(jìn)程都是通過發(fā)送數(shù)據(jù)到這個(gè)套接字上,然后由zygote進(jìn)程創(chuàng)建的。
這里還有一點(diǎn)說明的是:
在Zygote進(jìn)程中,會(huì)通過preload函數(shù)加載需要應(yīng)用程序都需要的公共資源。
預(yù)先加載這些公共資源有如下兩個(gè)好處:
- 加快應(yīng)用的啟動(dòng)速度 因?yàn)檫@些資源已經(jīng)在zygote進(jìn)程啟動(dòng)的時(shí)候加載好了
- 通過共享的方式節(jié)省內(nèi)存 這是Linux本身提供的機(jī)制:父進(jìn)程已經(jīng)加載的內(nèi)容可以在子進(jìn)程中進(jìn)行共享,而不用多份數(shù)據(jù)拷貝(除非子進(jìn)程對(duì)這些數(shù)據(jù)進(jìn)行了修改。)
preload的資源主要是Framework相關(guān)的一些基礎(chǔ)類和Resource資源,而這些資源正是所有應(yīng)用都需要的:
開發(fā)者通過Android SDK開發(fā)應(yīng)用所調(diào)用的API實(shí)現(xiàn)都在Framework中。
- static void preload() {
- Log.d(TAG, "begin preload");
- Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
- beginIcuCachePinning();
- Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
- Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
- preloadClasses();
- Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
- Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
- preloadResources();
- Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
- Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
- preloadOpenGL();
- Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
- preloadSharedLibraries();
- preloadTextResources();
- WebViewFactory.prepareWebViewInZygote();
- endIcuCachePinning();
- warmUpJcaProviders();
- Log.d(TAG, "end preload");
- }
system_server進(jìn)程
上文已經(jīng)提到,zygote進(jìn)程起來之后會(huì)根據(jù)需要啟動(dòng)system_server進(jìn)程。
system_server進(jìn)程中包含了大量的系統(tǒng)服務(wù)。例如:
- 負(fù)責(zé)網(wǎng)絡(luò)管理的NetworkManagementService
- 負(fù)責(zé)窗口管理的WindowManagerService
- 負(fù)責(zé)震動(dòng)管理的VibratorService
- 負(fù)責(zé)輸入管理的InputManagerService
等等。關(guān)于system_server,我們今后會(huì)其他的文章中專門講解,這里不做過多說明。
在本文中,我們只關(guān)注system_server中的ActivityManagerService這個(gè)系統(tǒng)服務(wù)。
ActivityManagerService
上文中提到:zygote進(jìn)程在啟動(dòng)之后會(huì)啟動(dòng)一個(gè)socket,然后一直在這個(gè)socket等待連接。
而會(huì)連接它的就是ActivityManagerService。因?yàn)锳ctivityManagerService掌控了所有應(yīng)用進(jìn)程的創(chuàng)建。
所有應(yīng)用程序的進(jìn)程都是由ActivityManagerService通過socket發(fā)送請(qǐng)求給Zygote進(jìn)程,然后由zygote fork創(chuàng)建的。
ActivityManagerService通過Process.start方法來請(qǐng)求zygote創(chuàng)建進(jìn)程:
- 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) {
- Log.e(LOG_TAG,
- "Starting VM process through Zygote failed");
- throw new RuntimeException(
- "Starting VM process through Zygote failed", ex);
- }
- }
這個(gè)函數(shù)會(huì)將啟動(dòng)進(jìn)程所需要的參數(shù)組裝好,并通過socket發(fā)送給zygote進(jìn)程。然后zygote進(jìn)程根據(jù)發(fā)送過來的參數(shù)將進(jìn)程fork出來。
在ActivityManagerService中,調(diào)用Process.start的地方是下面這個(gè)方法:
- private final void startProcessLocked(ProcessRecord app, String hostingType,
- String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
- ...
- 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);
- ...
- }
下文中我們會(huì)看到,所有四大組件進(jìn)程的創(chuàng)建,都是調(diào)用這里的startProcessLocked這個(gè)方法而創(chuàng)建的。
對(duì)于每一個(gè)應(yīng)用進(jìn)程,在ActivityManagerService中,都有一個(gè)ProcessRecord與之對(duì)應(yīng)。這個(gè)對(duì)象記錄了應(yīng)用進(jìn)程的所有詳細(xì)狀態(tài)。
PS:對(duì)于ProcessRecord的內(nèi)部結(jié)構(gòu),在下一篇文章中,我們會(huì)講解。
為了查找方便,對(duì)于每個(gè)ProcessRecord會(huì)存在下面兩個(gè)集合中。
- 按名稱和uid組織的集合:
- /**
- * All of the applications we currently have running organized by name.
- * The keys are strings of the application package name (as
- * returned by the package manager), and the keys are ApplicationRecord
- * objects.
- */
- final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
- 按pid組織的集合:
- /**
- * All of the processes we currently have running organized by pid.
- * The keys are the pid running the application.
- *
- * <p>NOTE: This object is protected by its own lock, NOT the global
- * activity manager lock!
- */
- final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
下面這幅圖小節(jié)了上文的這些內(nèi)容:
- <img src="http://qiangbo-workspace.oss-... width="600">
關(guān)于應(yīng)用組件
Processes and Threads 提到:
“當(dāng)某個(gè)應(yīng)用組件啟動(dòng)且該應(yīng)用沒有運(yùn)行其他任何組件時(shí),Android 系統(tǒng)會(huì)使用單個(gè)執(zhí)行線程為應(yīng)用啟動(dòng)新的 Linux 進(jìn)程。”
因此,四大組件中的任何一個(gè)先起來都會(huì)導(dǎo)致應(yīng)用進(jìn)程的創(chuàng)建。下文我們就詳細(xì)看一下,它們啟動(dòng)時(shí),各自是如何導(dǎo)致應(yīng)用進(jìn)程的創(chuàng)建的。
PS:四大組件的管理本身又是一個(gè)比較大的話題,限于篇幅關(guān)系,這里不會(huì)非常深入的講解,這里主要是講解四大組件與進(jìn)程創(chuàng)建的關(guān)系。
在應(yīng)用程序中,開發(fā)者通過:
- startActivity(Intent intent) 來啟動(dòng)Activity
- startService(Intent service) 來啟動(dòng)Service
- sendBroadcast(Intent intent) 來發(fā)送廣播
- ContentResolver 中的接口來使用ContentProvider
這其中,startActivity,startService和sendBroadcast還有一些重載方法。
其實(shí)這里提到的所有這些方法,最終都是通過Binder調(diào)用到ActivityManagerService中,由其進(jìn)行處理的。
這里特別說明一下:應(yīng)用進(jìn)程和ActivityManagerService所在進(jìn)程(即system_server進(jìn)程)是相互獨(dú)立的,兩個(gè)進(jìn)程之間的方法通常是不能直接互相調(diào)用的。
而Android系統(tǒng)中,專門提供了Binder框架來提供進(jìn)程間通訊和方法調(diào)用的能力。
調(diào)用關(guān)系如下圖所示:
<img src="http://qiangbo-workspace.oss-... width="600" >
Activity與進(jìn)程創(chuàng)建
在ActivityManagerService中,對(duì)每一個(gè)運(yùn)行中的Activity都有一個(gè)ActivityRecord對(duì)象與之對(duì)應(yīng),這個(gè)對(duì)象記錄Activity的詳細(xì)狀態(tài)。
ActivityManagerService中的startActivity方法接受Context.startActivity的請(qǐng)求,該方法代碼如下:
- @Override
- public final int startActivity(IApplicationThread caller, String callingPackage,
- Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
- return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
- resultWho, requestCode, startFlags, profilerInfo, bOptions,
- UserHandle.getCallingUserId());
- }
Activity的啟動(dòng)是一個(gè)非常復(fù)雜的過程。這里我們簡(jiǎn)單介紹一下背景知識(shí):
- ActivityManagerService中通過Stack和Task來管理Activity
- 每一個(gè)Activity都屬于一個(gè)Task,一個(gè)Task可能包含多個(gè)Activity。一個(gè)Stack包含多個(gè)Task
- ActivityStackSupervisor類負(fù)責(zé)管理所有的Stack
- Activity的啟動(dòng)過程會(huì)牽涉到:
- Intent的解析
- Stack,Task的查詢或創(chuàng)建
- Activity進(jìn)程的創(chuàng)建
- Activity窗口的創(chuàng)建
- Activity的生命周期調(diào)度
Activity的管理結(jié)構(gòu)如下圖所示:
<img src="http://qiangbo-workspace.oss-... width="500">
在Activity啟動(dòng)的***,會(huì)將前一個(gè)Activity pause,將新啟動(dòng)的Activity resume以便被用戶看到。
在這個(gè)時(shí)候,如果發(fā)現(xiàn)新啟動(dòng)的Activity進(jìn)程還沒有啟動(dòng),則會(huì)通過startSpecificActivityLocked將其啟動(dòng)。整個(gè)調(diào)用流程如下:
- ActivityManagerService.activityPaused =>
- ActivityStack.activityPausedLocked =>
- ActivityStack.completePauseLocked =>
- ActivityStackSupervisor.ensureActivitiesVisibleLocked =>
- ActivityStack.makeVisibleAndRestartIfNeeded =>
- ActivityStackSupervisor.startSpecificActivityLocked =>
- ActivityManagerService.startProcessLocked
- ActivityStackSupervisor.startSpecificActivityLocked 關(guān)鍵代碼如下:
- void startSpecificActivityLocked(ActivityRecord r,
- boolean andResume, boolean checkConfig) {
- // Is this activity's application already running?
- ProcessRecord app = mService.getProcessRecordLocked(r.processName,
- r.info.applicationInfo.uid, true);
- r.task.stack.setLaunchTime(r);
- if (app != null && app.thread != null) {
- ...
- }
- mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
- "activity", r.intent.getComponent(), false, false, true);
- }
這里的ProcessRecord app 描述了Activity所在進(jìn)程。
Service與進(jìn)程創(chuàng)建
Service的啟動(dòng)相對(duì)于Activity來說要簡(jiǎn)單一些。
在ActivityManagerService中,對(duì)每一個(gè)運(yùn)行中的Service都有一個(gè)ServiceRecord對(duì)象與之對(duì)應(yīng),這個(gè)對(duì)象記錄Service的詳細(xì)狀態(tài)。
ActivityManagerService中的startService方法處理Context.startServiceAPI的請(qǐng)求,相關(guān)代碼:
- @Override
- public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType, String callingPackage, int userId)
- throws TransactionTooLargeException {
- ...
- synchronized(this) {
- final int callingPid = Binder.getCallingPid();
- final int callingUid = Binder.getCallingUid();
- final long origId = Binder.clearCallingIdentity();
- ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, callingPid, callingUid, callingPackage, userId);
- Binder.restoreCallingIdentity(origId);
- return res;
- }
- }
這段代碼中的mServices對(duì)象是ActiveServices類型的,這個(gè)類專門負(fù)責(zé)管理活動(dòng)的Service。
啟動(dòng)Service的調(diào)用流程如下:
- ActivityManagerService.startService =>
- ActiveServices.startServiceLocked =>
- ActiveServices.startServiceInnerLocked =>
- ActiveServices.bringUpServiceLocked =>
- ActivityManagerService.startProcessLocked
ActiveServices.bringUpServiceLocked會(huì)判斷如果Service所在進(jìn)程還沒有啟動(dòng),
則通過ActivityManagerService.startProcessLocked將其啟動(dòng)。相關(guān)代碼如下:
- // Not running -- get it started, and enqueue this service record
- // to be executed when the app comes up.
- if (app == null && !permissionsReviewRequired) {
- if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
- "service", r.name, false, isolated, false)) == null) {
- String msg = "Unable to launch app "
- + r.appInfo.packageName + "/"
- + r.appInfo.uid + " for service "
- + r.intent.getIntent() + ": process is bad";
- Slog.w(TAG, msg);
- bringDownServiceLocked(r);
- return msg;
- }
- if (isolated) {
- r.isolatedProc = app;
- }
- }
這里的mAm 就是ActivityManagerService。
Provider與進(jìn)程創(chuàng)建
在ActivityManagerService中,對(duì)每一個(gè)運(yùn)行中的ContentProvider都有一個(gè)ContentProviderRecord對(duì)象與之對(duì)應(yīng),這個(gè)對(duì)象記錄ContentProvider的詳細(xì)狀態(tài)。
開發(fā)者通過ContentResolver中的insert, delete, update, query這些API來使用ContentProvider。在ContentResolver的實(shí)現(xiàn)中,無論使用這里的哪個(gè)接口,ContentResolver都會(huì)先通過acquireProvider 這個(gè)方法來獲取到一個(gè)類型為IContentProvider的遠(yuǎn)程接口。這個(gè)遠(yuǎn)程接口對(duì)接了ContentProvider的實(shí)現(xiàn)提供方。
同一個(gè)ContentProvider可能同時(shí)被多個(gè)模塊使用,而調(diào)用ContentResolver接口的進(jìn)程只是ContentProvider的一個(gè)客戶端而已,真正的ContentProvider提供方是運(yùn)行自身的進(jìn)程中的,兩個(gè)進(jìn)程的通訊需要通過Binder的遠(yuǎn)程接口形式來調(diào)用。如下圖所示:
<img src="http://qiangbo-workspace.oss-... width="500">
ContentResolver.acquireProvider 最終會(huì)調(diào)用到ActivityManagerService.getContentProvider中,該方法代碼如下:
- @Override
- public final ContentProviderHolder getContentProvider(
- IApplicationThread caller, String name, int userId, boolean stable) {
- enforceNotIsolatedCaller("getContentProvider");
- if (caller == null) {
- String msg = "null IApplicationThread when getting content provider "
- + name;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
- // with cross-user grant.
- return getContentProviderImpl(caller, name, null, stable, userId);
- }
而在getContentProviderImpl這個(gè)方法中,會(huì)判斷對(duì)應(yīng)的ContentProvider進(jìn)程有沒有啟動(dòng),
如果沒有,則通過startProcessLocked方法將其啟動(dòng)。
Receiver與進(jìn)程創(chuàng)建
開發(fā)者通過Context.sendBroadcast接口來發(fā)送廣播。ActivityManagerService.broadcastIntent 方法了對(duì)應(yīng)廣播發(fā)送的處理。
廣播是一種一對(duì)多的消息形式,廣播接受者的數(shù)量是不確定的。因此發(fā)送廣播本身可能是一個(gè)很耗時(shí)的過程(因?yàn)橐饌€(gè)通知)。
在ActivityManagerService內(nèi)部,是通過隊(duì)列的形式來管理廣播的:
- BroadcastQueue 描述了一個(gè)廣播隊(duì)列
- BroadcastRecord 描述了一個(gè)廣播事件
在ActivityManagerService中,如果收到了一個(gè)發(fā)送廣播的請(qǐng)求,會(huì)先創(chuàng)建一個(gè)BroadcastRecord接著將其放入BroadcastQueue中。
然后通知隊(duì)列自己去處理這個(gè)廣播。然后ActivityManagerService自己就可以繼續(xù)處理其他請(qǐng)求了。
廣播隊(duì)列本身是在另外一個(gè)線程處理廣播的發(fā)送的,這樣保證的ActivityManagerService主線程的負(fù)載不會(huì)太重。
在BroadcastQueue.processNextBroadcast(boolean fromMsg) 方法中真正實(shí)現(xiàn)了通知廣播事件到接受者的邏輯。在這個(gè)方法,如果發(fā)現(xiàn)接受者(即BrodcastReceiver)還沒有啟動(dòng),便會(huì)通過ActivityManagerService.startProcessLocked 方法將其啟動(dòng)。相關(guān)如下所示:
- final void processNextBroadcast(boolean fromMsg) {
- ...
- // Hard case: need to instantiate the receiver, possibly
- // starting its application process to host it.
- ResolveInfo info =
- (ResolveInfo)nextReceiver;
- ComponentName component = new ComponentName(
- info.activityInfo.applicationInfo.packageName,
- info.activityInfo.name);
- ...
- // Not running -- get it started, to be executed when the app comes up.
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
- "Need to start app ["
- + mQueueName + "] " + targetProcess + " for broadcast " + r);
- if ((r.curApp=mService.startProcessLocked(targetProcess,
- info.activityInfo.applicationInfo, true,
- r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
- "broadcast", r.curComponent,
- (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
- == null) {
- // Ah, this recipient is unavailable. Finish it if necessary,
- // and mark the broadcast record as ready for the next.
- Slog.w(TAG, "Unable to launch app "
- + info.activityInfo.applicationInfo.packageName + "/"
- + info.activityInfo.applicationInfo.uid + " for broadcast "
- + r.intent + ": process is bad");
- logBroadcastReceiverDiscardLocked(r);
- finishReceiverLocked(r, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, false);
- scheduleBroadcastsLocked();
- r.state = BroadcastRecord.IDLE;
- return;
- }
- mPendingBroadcast = r;
- mPendingBroadcastRecvIndex = recIdx;
- }
- }
至此,四大組件的啟動(dòng)就已經(jīng)分析完了。
結(jié)束語
進(jìn)程管理本身是一個(gè)非常大的話題,本文講解了Android系統(tǒng)中進(jìn)程創(chuàng)建的相關(guān)內(nèi)容。進(jìn)程啟動(dòng)之后該如何管理就是下一篇文章要講解的內(nèi)容了。
敬請(qǐng)期待。