Android系統中的進程管理

快41年了 8年前發布 | 8K 次閱讀 安卓開發 Android開發 移動開發

對于操作系統來說,進程管理是其最重要的職責之一。

考慮到這部分的內容較多,因此會拆分成幾篇文章來講解。

本文是進程管理系統文章的第一篇,會講解Android系統中的進程創建。

本文適合Android平臺的應用程序開發者,也適合對于Android系統內部實現感興趣的讀者。

概述

Android系統以Linux內核為基礎,所以對于進程的管理自然離不開Linux本身提供的機制。例如:

1.通過fork來創建進行

2.通過信號量來管理進程

3.通過proc文件系統來查詢和調整進程狀態等

對于Android來說,進程管理的主要內容包括以下幾個部分內容:

1.進程的創建

2.進程的優先級管理

3.進程的內存管理

4.進程的回收和死亡處理

本文會專門講解進程的創建,其余部分將在后面的文章中講解。

主要模塊

為了便于下文的講解,這里先介紹一下Android系統中牽涉到進程創建的幾個主要模塊。

同時為了便于讀者更詳細的了解這些模塊,這里也同時提供了這些模塊的代碼路徑。

這里提到的代碼路徑是指AOSP的源碼數中的路徑。

關于如何獲取AOSP源碼請參見這里:Downloading the Source。

本文以Android N版本的代碼為示例,所用到的Source Code Tags是:android-7.0.0_r1。

相關模塊:

app_process

代碼路徑:frameworks/base/cmds/app_process

說明:app_process是一個可執行程序,該程序的主要作用是啟動zygote和system_server進程。

Zygote

代碼路徑:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

說明:zygote進程是所有應用進程的父進程,這是系統中一個非常重要的進程,下文我們會詳細講解。

ActivityManager

代碼路徑:frameworks/base/services/core/java/com/android/server/am/

說明:am是ActivityManager的縮寫。

這個目錄下的代碼負責了Android全部四大組件(Activity,Service,ContentProvider,BroadcastReceiver)的管理,并且還掌控了所有應用程序進程的創建和進程的優先級管理。

因此,這個部分的內容將是本系列文章講解的重點。

進程與線程

Android官方開發網站的這篇文章:Processes and Threads 非常好的介紹了Android系統中進程相關的一些基本概念和重要知識。

在閱讀下文之前,請務必將這篇文章瀏覽一遍。

關于進程

在Android系統中,進程可以大致分為系統進程和應用進程兩大類。

系統進程是系統內置的(例如:init,zygote,system_server進程),屬于操作系統必不可少的一部分。系統進程的作用在于:

1.管理硬件設備

2.提供訪問設備的基本能力

3.管理應用進程

應用進程是指應用程序運行的進程。這些應用程序可能是系統出廠自帶的(例如Launcher,電話,短信等應用),也可能是用戶自己安裝的(例如:微信,支付寶等)。

系統進程的數量通常是固定的(出廠或者系統升級之后就確定了),并且系統進程通常是一直存活,常駐內存的。系統進程的異常退出將可能導致設備無法正常使用。

而應用程序和應用進程在每個人使用的設備上通常是各不一樣的。如何管理好這些不確定的應用進程,就是操作系統本身要仔細考慮的內容。也是衡量一個操作系統好壞的標準之一。

在本文中,我們會介紹init,zygote和system_server三個系統進程。

除此之外,本系列文章將會把主要精力集中在講解Android系統如何管理應用進程上。

init進程

init進程是一切的開始,在Android系統中,所有進程的進程號都是不確定的,唯獨init進程的進程號一定是1。

因為這個進程一定是系統起來的第一個進程。并且,init進程掌控了整個系統的啟動邏輯。

我們知道,Android可能運行在各種不同的平臺,不同的設備上。因此,啟動的邏輯是不盡相同的。

為了適應各種平臺和設備的需求,init進程的初始化工作通過init.rc配置文件來管理。

你可以在AOSP源碼的system/core/rootdir/路徑找到這些配置文件。

配置文件的主入口文件是init.rc,這個文件會通過import引入其他幾個文件。

在本文中,我們統稱這些文件為init.rc。

init.rc通過Android Init Language來進行配置。

建議讀者大致閱讀一下其 語法說明 。

init.rc中配置了系統啟動的時候該做哪些事情,以及啟動哪些系統進程。

這其中有兩個特別重要的進程就是:zygote和system_server進程。

zygote的中文意思是“受精卵“。這是一個很有寓意的名稱:所有的應用進程都是由zygote fork出來的子進程,因此zygote進程是所有應用進程的父進程。

system_server 這個進程正如其名稱一樣,這是一個系統服務器。Framework層的幾乎所有服務都位于這個進程中。這其中就包括管理四大組件的ActivityManagerService。

Zygote進程

init.rc文件會根據平臺不一樣,選擇下面幾個文件中的一個來啟動zygote進程:

1.init.zygote32.rc

2.init.zygote32_64.rc

3.init.zygote64.rc

4.init.zygote64_32.rc

這幾個文件的內容是大致一致的,僅僅是為了不同平臺服務的。這里我們以init.zygote32.rc的文件為例,來看看其中的內容:

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

在這段配置文件中(如果你不明白這段配置的含義,請閱讀一下文檔:Android Init Language),啟動了一個名稱叫做zygote的服務進程。這個進程是通過/system/bin/app_process 這個可執行程序創建的。

并且在啟動這個可執行程序的時候,傳遞了`-Xzygote /system/bin --zygote --start-system-server

class main` 這些參數。

要知道這里到底做了什么,我們需要看一下app_process的源碼。

app_process的源碼在這個路徑:frameworks/base/cmds/app_process/app_main.cpp。

這個文件的main函數的有如下代碼:

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; 
        } 
    }

這里會判斷

1.如果執行這個命令時帶了--zygote參數,就會通過runtime.start啟動com.android.internal.os.ZygoteInit。

2.如果參數中帶有--start-system-server參數,就會將start-system-server添加到args中。

這段代碼是C++實現的。在執行這段代碼的時候還沒有任何Java的環境。而runtime.start就是啟動Java虛擬機,并在虛擬機中啟動指定的類。于是接下來的邏輯就在ZygoteInit.java中了。

這個文件的main函數主要代碼如下:

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; 
        } 
    }

在這段代碼中,我們主要關注如下幾行:

1.通過 registerZygoteSocket(socketName); 注冊Zygote Socket

2.通過 preload(); 預先加載所有應用都需要的公共資源

3.通過 startSystemServer(abiList, socketName); 啟動system_server

4.通過 runSelectLoop(abiList); 在Looper上等待連接

這里需要說明的是:zygote進程啟動之后,會啟動一個socket套接字,并通過Looper一直在這個套接字上等待連接。

所有應用進程都是通過發送數據到這個套接字上,然后由zygote進程創建的。

這里還有一點說明的是:

在Zygote進程中,會通過preload函數加載需要應用程序都需要的公共資源。

預先加載這些公共資源有如下兩個好處:

1.加快應用的啟動速度 因為這些資源已經在zygote進程啟動的時候加載好了

2.通過共享的方式節省內存 這是Linux本身提供的機制:父進程已經加載的內容可以在子進程中進行共享,而不用多份數據拷貝(除非子進程對這些數據進行了修改。)

preload的資源主要是Framework相關的一些基礎類和Resource資源,而這些資源正是所有應用都需要的:

開發者通過Android SDK開發應用所調用的API實現都在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進程

上文已經提到,zygote進程起來之后會根據需要啟動system_server進程。

system_server進程中包含了大量的系統服務。例如:

1.負責網絡管理的NetworkManagementService

2.負責窗口管理的WindowManagerService

3.負責震動管理的VibratorService

4.負責輸入管理的InputManagerService

等等。關于system_server,我們今后會其他的文章中專門講解,這里不做過多說明。

在本文中,我們只關注system_server中的ActivityManagerService這個系統服務。

ActivityManagerService

上文中提到:zygote進程在啟動之后會啟動一個socket,然后一直在這個socket等待連接。

而會連接它的就是ActivityManagerService。因為ActivityManagerService掌控了所有應用進程的創建。

所有應用程序的進程都是由ActivityManagerService通過socket發送請求給Zygote進程,然后由zygote fork創建的。

ActivityManagerService通過Process.start方法來請求zygote創建進程:

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); 
       } 
    }

這個函數會將啟動進程所需要的參數組裝好,并通過socket發送給zygote進程。然后zygote進程根據發送過來的參數將進程fork出來。

在ActivityManagerService中,調用Process.start的地方是下面這個方法:

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); 
    ... 
    }

下文中我們會看到,所有四大組件進程的創建,都是調用這里的startProcessLocked這個方法而創建的。

對于每一個應用進程,在ActivityManagerService中,都有一個ProcessRecord與之對應。這個對象記錄了應用進程的所有詳細狀態。

PS:對于ProcessRecord的內部結構,在下一篇文章中,我們會講解。

為了查找方便,對于每個ProcessRecord會存在下面兩個集合中。

按名稱和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>();

下面這幅圖小節了上文的這些內容:

<img src="http://qiangbo-workspace.oss-... width="600">

關于應用組件

Processes and Threads 提到:

“當某個應用組件啟動且該應用沒有運行其他任何組件時,Android 系統會使用單個執行線程為應用啟動新的 Linux 進程。”

因此,四大組件中的任何一個先起來都會導致應用進程的創建。下文我們就詳細看一下,它們啟動時,各自是如何導致應用進程的創建的。

PS:四大組件的管理本身又是一個比較大的話題,限于篇幅關系,這里不會非常深入的講解,這里主要是講解四大組件與進程創建的關系。

在應用程序中,開發者通過:

1.startActivity(Intent intent) 來啟動Activity

2.startService(Intent service) 來啟動Service

3.sendBroadcast(Intent intent) 來發送廣播

4.ContentResolver 中的接口來使用ContentProvider

這其中,startActivity,startService和sendBroadcast還有一些重載方法。

其實這里提到的所有這些方法,最終都是通過Binder調用到ActivityManagerService中,由其進行處理的。

這里特別說明一下:應用進程和ActivityManagerService所在進程(即system_server進程)是相互獨立的,兩個進程之間的方法通常是不能直接互相調用的。

而Android系統中,專門提供了Binder框架來提供進程間通訊和方法調用的能力。

調用關系如下圖所示:

<img src="http://qiangbo-workspace.oss-... width="600" >

Activity與進程創建

在ActivityManagerService中,對每一個運行中的Activity都有一個ActivityRecord對象與之對應,這個對象記錄Activity的詳細狀態。

ActivityManagerService中的startActivity方法接受Context.startActivity的請求,該方法代碼如下:

@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的啟動是一個非常復雜的過程。這里我們簡單介紹一下背景知識:

1.ActivityManagerService中通過Stack和Task來管理Activity

2.每一個Activity都屬于一個Task,一個Task可能包含多個Activity。一個Stack包含多個Task

3.ActivityStackSupervisor類負責管理所有的Stack

4.Activity的啟動過程會牽涉到:

a.Intent的解析

b.Stack,Task的查詢或創建

c.Activity進程的創建

d.Activity窗口的創建

e.Activity的生命周期調度

Activity的管理結構如下圖所示:

<img src="http://qiangbo-workspace.oss-... width="500">

在Activity啟動的最后,會將前一個Activity pause,將新啟動的Activity resume以便被用戶看到。

在這個時候,如果發現新啟動的Activity進程還沒有啟動,則會通過startSpecificActivityLocked將其啟動。整個調用流程如下:

1.ActivityManagerService.activityPaused =>

2.ActivityStack.activityPausedLocked =>

3.ActivityStack.completePauseLocked =>

4.ActivityStackSupervisor.ensureActivitiesVisibleLocked =>

5.ActivityStack.makeVisibleAndRestartIfNeeded =>

6.ActivityStackSupervisor.startSpecificActivityLocked =>

7.ActivityManagerService.startProcessLocked

8.ActivityStackSupervisor.startSpecificActivityLocked 關鍵代碼如下:

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所在進程。

Service與進程創建

Service的啟動相對于Activity來說要簡單一些。

在ActivityManagerService中,對每一個運行中的Service都有一個ServiceRecord對象與之對應,這個對象記錄Service的詳細狀態。

ActivityManagerService中的startService方法處理Context.startServiceAPI的請求,相關代碼:

@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對象是ActiveServices類型的,這個類專門負責管理活動的Service。

啟動Service的調用流程如下:

1.ActivityManagerService.startService =>

2.ActiveServices.startServiceLocked =>

3.ActiveServices.startServiceInnerLocked =>

4.ActiveServices.bringUpServiceLocked =>

5.ActivityManagerService.startProcessLocked

ActiveServices.bringUpServiceLocked會判斷如果Service所在進程還沒有啟動,

則通過ActivityManagerService.startProcessLocked將其啟動。相關代碼如下:

// 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與進程創建

在ActivityManagerService中,對每一個運行中的ContentProvider都有一個ContentProviderRecord對象與之對應,這個對象記錄ContentProvider的詳細狀態。

開發者通過ContentResolver中的insert, delete, update, query這些API來使用ContentProvider。在ContentResolver的實現中,無論使用這里的哪個接口,ContentResolver都會先通過acquireProvider 這個方法來獲取到一個類型為IContentProvider的遠程接口。這個遠程接口對接了ContentProvider的實現提供方。

同一個ContentProvider可能同時被多個模塊使用,而調用ContentResolver接口的進程只是ContentProvider的一個客戶端而已,真正的ContentProvider提供方是運行自身的進程中的,兩個進程的通訊需要通過Binder的遠程接口形式來調用。如下圖所示:

<img src="http://qiangbo-workspace.oss-... width="500">

ContentResolver.acquireProvider 最終會調用到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這個方法中,會判斷對應的ContentProvider進程有沒有啟動,

如果沒有,則通過startProcessLocked方法將其啟動。

Receiver與進程創建

開發者通過Context.sendBroadcast接口來發送廣播。ActivityManagerService.broadcastIntent 方法了對應廣播發送的處理。

廣播是一種一對多的消息形式,廣播接受者的數量是不確定的。因此發送廣播本身可能是一個很耗時的過程(因為要逐個通知)。

在ActivityManagerService內部,是通過隊列的形式來管理廣播的:

1.BroadcastQueue 描述了一個廣播隊列

2.BroadcastRecord 描述了一個廣播事件

在ActivityManagerService中,如果收到了一個發送廣播的請求,會先創建一個BroadcastRecord接著將其放入BroadcastQueue中。

然后通知隊列自己去處理這個廣播。然后ActivityManagerService自己就可以繼續處理其他請求了。

廣播隊列本身是在另外一個線程處理廣播的發送的,這樣保證的ActivityManagerService主線程的負載不會太重。

在BroadcastQueue.processNextBroadcast(boolean fromMsg) 方法中真正實現了通知廣播事件到接受者的邏輯。在這個方法,如果發現接受者(即BrodcastReceiver)還沒有啟動,便會通過ActivityManagerService.startProcessLocked 方法將其啟動。相關如下所示:

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; 
       } 
    }

至此,四大組件的啟動就已經分析完了。

結束語

進程管理本身是一個非常大的話題,本文講解了Android系統中進程創建的相關內容。

 

 

來自:http://www.uml.org.cn/mobiledev/201611241.asp

 

 本文由用戶 快41年了 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!