Android系统中的进程管理:进程的创建

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介:

对于操作系统来说,进程管理是其最重要的职责之一。

考虑到这部分的内容较多,因此会拆分成几篇文章来讲解。

本文是进程管理系统文章的第一篇,会讲解Android系统中的进程创建。

本文适合Android平台的应用程序开发者,也适合对于Android系统内部实现感兴趣的读者。

概述

Android系统以Linux内核为基础,所以对于进程的管理自然离不开Linux本身提供的机制。例如:

  • 通过fork来创建进行
  • 通过信号量来管理进程
  • 通过proc文件系统来查询和调整进程状态等

对于Android来说,进程管理的主要内容包括以下几个部分内容:

  • 进程的创建
  • 进程的优先级管理
  • 进程的内存管理
  • 进程的回收和死亡处理

本文会专门讲解进程的创建,其余部分将在后面的文章中讲解。

主要模块

为了便于下文的讲解,这里先介绍一下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进程),属于操作系统必不可少的一部分。系统进程的作用在于:

  • 管理硬件设备
  • 提供访问设备的基本能力
  • 管理应用进程

应用进程是指应用程序运行的进程。这些应用程序可能是系统出厂自带的(例如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进程:

  • init.zygote32.rc
  • init.zygote32_64.rc
  • init.zygote64.rc
  • init.zygote64_32.rc

这几个文件的内容是大致一致的,仅仅是为了不同平台服务的。这里我们以init.zygote32.rc的文件为例,来看看其中的内容:

 
 
  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 
  2.  
  3. class main 
  4.  
  5. socket zygote stream 660 root system 
  6.  
  7. onrestart write /sys/android_power/request_state wake 
  8.  
  9. onrestart write /sys/power/state on 
  10.  
  11. onrestart restart audioserver 
  12.  
  13. onrestart restart cameraserver 
  14.  
  15. onrestart restart media 
  16.  
  17. onrestart restart netd 
  18.  
  19. 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函数的有如下代码:

 
 
  1. int main(int argc, char* const argv[]) 
  2. ... 
  3.     while (i < argc) { 
  4.         const char* arg = argv[i++]; 
  5.         if (strcmp(arg, "--zygote") == 0) { 
  6.             zygote = true
  7.             niceName = ZYGOTE_NICE_NAME; 
  8.         } else if (strcmp(arg, "--start-system-server") == 0) { 
  9.             startSystemServer = true
  10.         ... 
  11.     } 
  12.     ... 
  13.    if (!className.isEmpty()) { 
  14.         ... 
  15.     } else { 
  16.        ... 
  17.      
  18.        if (startSystemServer) { 
  19.            args.add(String8("start-system-server")); 
  20.        } 
  21.     } 
  22. ... 
  23.     if (zygote) { 
  24.         runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 
  25.     } else if (className) { 
  26.         runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 
  27.     } else { 
  28.         fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 
  29.         app_usage(); 
  30.         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 
  31.         return 10; 
  32.     } 
  33.  

这里会判断,

  • 如果执行这个命令时带了--zygote参数,就会通过runtime.start启动com.android.internal.os.ZygoteInit。
  • 如果参数中带有--start-system-server参数,就会将start-system-server添加到args中。

这段代码是C++实现的。在执行这段代码的时候还没有任何Java的环境。而runtime.start就是启动Java虚拟机,并在虚拟机中启动指定的类。于是接下来的逻辑就在ZygoteInit.java中了。

这个文件的main函数主要代码如下:

 
 
  1. public static void main(String argv[]) { 
  2.    ... 
  3.  
  4.    try { 
  5.        ... 
  6.  
  7.        boolean startSystemServer = false
  8.        String socketName = "zygote"
  9.        String abiList = null
  10.        for (int i = 1; i < argv.length; i++) { 
  11.            if ("start-system-server".equals(argv[i])) { 
  12.                startSystemServer = true
  13.            } else if (argv[i].startsWith(ABI_LIST_ARG)) { 
  14.                ... 
  15.            } 
  16.        } 
  17.        ... 
  18.        registerZygoteSocket(socketName); 
  19.        ... 
  20.        preload(); 
  21.        ... 
  22.        Zygote.nativeUnmountStorageOnInit(); 
  23.  
  24.        ZygoteHooks.stopZygoteNoThreadCreation(); 
  25.  
  26.        if (startSystemServer) { 
  27.            startSystemServer(abiList, socketName); 
  28.        } 
  29.  
  30.        Log.i(TAG, "Accepting command socket connections"); 
  31.        runSelectLoop(abiList); 
  32.  
  33.        closeServerSocket(); 
  34.    } catch (MethodAndArgsCaller caller) { 
  35.        caller.run(); 
  36.    } catch (RuntimeException ex) { 
  37.        Log.e(TAG, "Zygote died with exception", ex); 
  38.        closeServerSocket(); 
  39.        throw ex; 
  40.    } 
  41.  

在这段代码中,我们主要关注如下几行:

  1. 通过 registerZygoteSocket(socketName); 注册Zygote Socket
  2. 通过 preload(); 预先加载所有应用都需要的公共资源
  3. 通过 startSystemServer(abiList, socketName); 启动system_server
  4. 通过 runSelectLoop(abiList); 在Looper上等待连接

这里需要说明的是:zygote进程启动之后,会启动一个socket套接字,并通过Looper一直在这个套接字上等待连接。

所有应用进程都是通过发送数据到这个套接字上,然后由zygote进程创建的。

这里还有一点说明的是:

在Zygote进程中,会通过preload函数加载需要应用程序都需要的公共资源。

预先加载这些公共资源有如下两个好处:

  • 加快应用的启动速度 因为这些资源已经在zygote进程启动的时候加载好了
  • 通过共享的方式节省内存 这是Linux本身提供的机制:父进程已经加载的内容可以在子进程中进行共享,而不用多份数据拷贝(除非子进程对这些数据进行了修改。)

preload的资源主要是Framework相关的一些基础类和Resource资源,而这些资源正是所有应用都需要的:

开发者通过Android SDK开发应用所调用的API实现都在Framework中。

 
 
  1. static void preload() { 
  2.    Log.d(TAG, "begin preload"); 
  3.    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning"); 
  4.    beginIcuCachePinning(); 
  5.    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); 
  6.    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses"); 
  7.    preloadClasses(); 
  8.    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); 
  9.    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources"); 
  10.    preloadResources(); 
  11.    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); 
  12.    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL"); 
  13.    preloadOpenGL(); 
  14.    Trace.traceEnd(Trace.TRACE_TAG_DALVIK); 
  15.    preloadSharedLibraries(); 
  16.    preloadTextResources(); 
  17.  
  18.    WebViewFactory.prepareWebViewInZygote(); 
  19.    endIcuCachePinning(); 
  20.    warmUpJcaProviders(); 
  21.    Log.d(TAG, "end preload"); 
  22.  

system_server进程

上文已经提到,zygote进程起来之后会根据需要启动system_server进程。

system_server进程中包含了大量的系统服务。例如:

  • 负责网络管理的NetworkManagementService
  • 负责窗口管理的WindowManagerService
  • 负责震动管理的VibratorService
  • 负责输入管理的InputManagerService

等等。关于system_server,我们今后会其他的文章中专门讲解,这里不做过多说明。

在本文中,我们只关注system_server中的ActivityManagerService这个系统服务。

ActivityManagerService

上文中提到:zygote进程在启动之后会启动一个socket,然后一直在这个socket等待连接。

而会连接它的就是ActivityManagerService。因为ActivityManagerService掌控了所有应用进程的创建。

所有应用程序的进程都是由ActivityManagerService通过socket发送请求给Zygote进程,然后由zygote fork创建的。

ActivityManagerService通过Process.start方法来请求zygote创建进程:

 
 
  1. public static final ProcessStartResult start(final String processClass, 
  2.                              final String niceName, 
  3.                              int uid, int gid, int[] gids, 
  4.                              int debugFlags, int mountExternal, 
  5.                              int targetSdkVersion, 
  6.                              String seInfo, 
  7.                              String abi, 
  8.                              String instructionSet, 
  9.                              String appDataDir, 
  10.                              String[] zygoteArgs) { 
  11.    try { 
  12.        return startViaZygote(processClass, niceName, uid, gid, gids, 
  13.                debugFlags, mountExternal, targetSdkVersion, seInfo, 
  14.                abi, instructionSet, appDataDir, zygoteArgs); 
  15.    } catch (ZygoteStartFailedEx ex) { 
  16.        Log.e(LOG_TAG, 
  17.                "Starting VM process through Zygote failed"); 
  18.        throw new RuntimeException( 
  19.                "Starting VM process through Zygote failed", ex); 
  20.    } 
  21.  

这个函数会将启动进程所需要的参数组装好,并通过socket发送给zygote进程。然后zygote进程根据发送过来的参数将进程fork出来。

在ActivityManagerService中,调用Process.start的地方是下面这个方法:

 
 
  1. private final void startProcessLocked(ProcessRecord app, String hostingType, 
  2.        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { 
  3.         
  4. ... 
  5.   Process.ProcessStartResult startResult = Process.start(entryPoint, 
  6.           app.processName, uid, uid, gids, debugFlags, mountExternal, 
  7.           app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, 
  8.           app.info.dataDir, entryPointArgs); 
  9. ... 
  10.  

下文中我们会看到,所有四大组件进程的创建,都是调用这里的startProcessLocked这个方法而创建的。

对于每一个应用进程,在ActivityManagerService中,都有一个ProcessRecord与之对应。这个对象记录了应用进程的所有详细状态。

PS:对于ProcessRecord的内部结构,在下一篇文章中,我们会讲解。

为了查找方便,对于每个ProcessRecord会存在下面两个集合中。

  • 按名称和uid组织的集合:
 
 
  1. /** 
  2. All of the applications we currently have running organized by name
  3. * The keys are strings of the application package name (as 
  4. * returned by the package manager), and the keys are ApplicationRecord 
  5. * objects. 
  6. */ 
  7. final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();  
  • 按pid组织的集合:
 
 
  1. /** 
  2. All of the processes we currently have running organized by pid. 
  3. * The keys are the pid running the application. 
  4. * <p>NOTE: This object is protected by its own lock, NOT the global 
  5. * activity manager lock! 
  6. */ 
  7. final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();  

下面这幅图小节了上文的这些内容:

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

关于应用组件

Processes and Threads 提到:

“当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。”

因此,四大组件中的任何一个先起来都会导致应用进程的创建。下文我们就详细看一下,它们启动时,各自是如何导致应用进程的创建的。

PS:四大组件的管理本身又是一个比较大的话题,限于篇幅关系,这里不会非常深入的讲解,这里主要是讲解四大组件与进程创建的关系。

在应用程序中,开发者通过:

  • startActivity(Intent intent) 来启动Activity
  • startService(Intent service) 来启动Service
  • sendBroadcast(Intent intent) 来发送广播
  • 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的请求,该方法代码如下:

 
 
  1. @Override 
  2. public final int startActivity(IApplicationThread caller, String callingPackage, 
  3.        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, 
  4.        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { 
  5.    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, 
  6.            resultWho, requestCode, startFlags, profilerInfo, bOptions, 
  7.            UserHandle.getCallingUserId()); 
  8.  

Activity的启动是一个非常复杂的过程。这里我们简单介绍一下背景知识:

  • ActivityManagerService中通过Stack和Task来管理Activity
  • 每一个Activity都属于一个Task,一个Task可能包含多个Activity。一个Stack包含多个Task
  • ActivityStackSupervisor类负责管理所有的Stack
  • Activity的启动过程会牵涉到:
    • Intent的解析
    • Stack,Task的查询或创建
    • Activity进程的创建
    • Activity窗口的创建
    • Activity的生命周期调度

Activity的管理结构如下图所示:

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

在Activity启动的最后,会将前一个Activity pause,将新启动的Activity resume以便被用户看到。

在这个时候,如果发现新启动的Activity进程还没有启动,则会通过startSpecificActivityLocked将其启动。整个调用流程如下:

  • ActivityManagerService.activityPaused =>
  • ActivityStack.activityPausedLocked =>
  • ActivityStack.completePauseLocked =>
  • ActivityStackSupervisor.ensureActivitiesVisibleLocked =>
  • ActivityStack.makeVisibleAndRestartIfNeeded =>
  • ActivityStackSupervisor.startSpecificActivityLocked =>
  • ActivityManagerService.startProcessLocked
  • ActivityStackSupervisor.startSpecificActivityLocked 关键代码如下:
 
 
  1. void startSpecificActivityLocked(ActivityRecord r, 
  2.        boolean andResume, boolean checkConfig) { 
  3.    // Is this activity's application already running? 
  4.    ProcessRecord app = mService.getProcessRecordLocked(r.processName, 
  5.            r.info.applicationInfo.uid, true); 
  6.  
  7.    r.task.stack.setLaunchTime(r); 
  8.  
  9.    if (app != null && app.thread != null) { 
  10.        ... 
  11.    } 
  12.  
  13.    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, 
  14.            "activity", r.intent.getComponent(), falsefalsetrue); 
  15.  

这里的ProcessRecord app 描述了Activity所在进程。

Service与进程创建

Service的启动相对于Activity来说要简单一些。

在ActivityManagerService中,对每一个运行中的Service都有一个ServiceRecord对象与之对应,这个对象记录Service的详细状态。

ActivityManagerService中的startService方法处理Context.startServiceAPI的请求,相关代码:

 
 
  1. @Override 
  2. public ComponentName startService(IApplicationThread caller, Intent service, 
  3.        String resolvedType, String callingPackage, int userId) 
  4.        throws TransactionTooLargeException { 
  5.    ... 
  6.    synchronized(this) { 
  7.        final int callingPid = Binder.getCallingPid(); 
  8.        final int callingUid = Binder.getCallingUid(); 
  9.        final long origId = Binder.clearCallingIdentity(); 
  10.        ComponentName res = mServices.startServiceLocked(caller, service, 
  11.                resolvedType, callingPid, callingUid, callingPackage, userId); 
  12.        Binder.restoreCallingIdentity(origId); 
  13.        return res; 
  14.    } 
  15.  

这段代码中的mServices对象是ActiveServices类型的,这个类专门负责管理活动的Service。

启动Service的调用流程如下:

  • ActivityManagerService.startService =>
  • ActiveServices.startServiceLocked =>
  • ActiveServices.startServiceInnerLocked =>
  • ActiveServices.bringUpServiceLocked =>
  • ActivityManagerService.startProcessLocked

ActiveServices.bringUpServiceLocked会判断如果Service所在进程还没有启动,

则通过ActivityManagerService.startProcessLocked将其启动。相关代码如下:

 
 
  1. // Not running -- get it started, and enqueue this service record 
  2. // to be executed when the app comes up. 
  3. if (app == null && !permissionsReviewRequired) { 
  4.   if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, 
  5.           "service", r.namefalse, isolated, false)) == null) { 
  6.       String msg = "Unable to launch app " 
  7.               + r.appInfo.packageName + "/" 
  8.               + r.appInfo.uid + " for service " 
  9.               + r.intent.getIntent() + ": process is bad"
  10.       Slog.w(TAG, msg); 
  11.       bringDownServiceLocked(r); 
  12.       return msg; 
  13.   } 
  14.   if (isolated) { 
  15.       r.isolatedProc = app; 
  16.   } 

这里的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中,该方法代码如下:

 
 
  1. @Override 
  2. public final ContentProviderHolder getContentProvider( 
  3.        IApplicationThread caller, String nameint userId, boolean stable) { 
  4.    enforceNotIsolatedCaller("getContentProvider"); 
  5.    if (caller == null) { 
  6.        String msg = "null IApplicationThread when getting content provider " 
  7.                + name
  8.        Slog.w(TAG, msg); 
  9.        throw new SecurityException(msg); 
  10.    } 
  11.    // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal 
  12.    // with cross-user grant
  13.    return getContentProviderImpl(caller, namenull, stable, userId); 
  14.  

而在getContentProviderImpl这个方法中,会判断对应的ContentProvider进程有没有启动,

如果没有,则通过startProcessLocked方法将其启动。

Receiver与进程创建

开发者通过Context.sendBroadcast接口来发送广播。ActivityManagerService.broadcastIntent 方法了对应广播发送的处理。

广播是一种一对多的消息形式,广播接受者的数量是不确定的。因此发送广播本身可能是一个很耗时的过程(因为要逐个通知)。

在ActivityManagerService内部,是通过队列的形式来管理广播的:

  • BroadcastQueue 描述了一个广播队列
  • BroadcastRecord 描述了一个广播事件

在ActivityManagerService中,如果收到了一个发送广播的请求,会先创建一个BroadcastRecord接着将其放入BroadcastQueue中。

然后通知队列自己去处理这个广播。然后ActivityManagerService自己就可以继续处理其他请求了。

广播队列本身是在另外一个线程处理广播的发送的,这样保证的ActivityManagerService主线程的负载不会太重。

在BroadcastQueue.processNextBroadcast(boolean fromMsg) 方法中真正实现了通知广播事件到接受者的逻辑。在这个方法,如果发现接受者(即BrodcastReceiver)还没有启动,便会通过ActivityManagerService.startProcessLocked 方法将其启动。相关如下所示:

 
 
  1. final void processNextBroadcast(boolean fromMsg) { 
  2.     ... 
  3.        // Hard case: need to instantiate the receiver, possibly 
  4.        // starting its application process to host it. 
  5.  
  6.        ResolveInfo info = 
  7.            (ResolveInfo)nextReceiver; 
  8.        ComponentName component = new ComponentName( 
  9.                info.activityInfo.applicationInfo.packageName, 
  10.                info.activityInfo.name); 
  11.     ... 
  12.        // Not running -- get it started, to be executed when the app comes up. 
  13.        if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST, 
  14.                "Need to start app [" 
  15.                + mQueueName + "] " + targetProcess + " for broadcast " + r); 
  16.        if ((r.curApp=mService.startProcessLocked(targetProcess, 
  17.                info.activityInfo.applicationInfo, true
  18.                r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, 
  19.                "broadcast", r.curComponent, 
  20.                (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, falsefalse)) 
  21.                        == null) { 
  22.            // Ah, this recipient is unavailable.  Finish it if necessary, 
  23.            // and mark the broadcast record as ready for the next
  24.            Slog.w(TAG, "Unable to launch app " 
  25.                    + info.activityInfo.applicationInfo.packageName + "/" 
  26.                    + info.activityInfo.applicationInfo.uid + " for broadcast " 
  27.                    + r.intent + ": process is bad"); 
  28.            logBroadcastReceiverDiscardLocked(r); 
  29.            finishReceiverLocked(r, r.resultCode, r.resultData, 
  30.                    r.resultExtras, r.resultAbort, false); 
  31.            scheduleBroadcastsLocked(); 
  32.            r.state = BroadcastRecord.IDLE; 
  33.            return
  34.        } 
  35.  
  36.        mPendingBroadcast = r; 
  37.        mPendingBroadcastRecvIndex = recIdx; 
  38.    } 
  39.  

至此,四大组件的启动就已经分析完了。

结束语

进程管理本身是一个非常大的话题,本文讲解了Android系统中进程创建的相关内容。进程启动之后该如何管理就是下一篇文章要讲解的内容了。

敬请期待。




作者:paulquei
来源:51CTO
相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
目录
相关文章
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
201 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(二)
|
开发工具 Android开发 C++
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
190 0
【Android 逆向】Android 进程注入工具开发 ( 总结 | 源码编译 | 逆向环境搭建使用 | 使用进程注入工具进行逆向操作 ) ★★★(一)
|
Java Linux Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
164 0
|
Android开发 C语言
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
244 0
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
【Android 逆向】Android 进程注入工具开发 ( 远程调用 | x86 架构的返回值获取 | arm 架构远程调用 )
264 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具收尾操作 | 关闭注入的动态库 | 恢复寄存器 | 脱离远程调试附着 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具收尾操作 | 关闭注入的动态库 | 恢复寄存器 | 脱离远程调试附着 )
157 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取注入的 libbridge.so 动态库中的 load 函数地址 并 通过 远程调用 执行该函数 )
181 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 linker 中的 dlopen 函数地址 并 通过 远程调用 执行该函数 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 linker 中的 dlopen 函数地址 并 通过 远程调用 执行该函数 )
211 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )
139 0
|
Android开发
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
139 0

相关实验场景

更多