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

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

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

本文是进程管理系统文章的第一篇,会讲解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(), false, false, true); 
  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.name, false, 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 name, int 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, name, null, 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, false, false)) 
  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

时间: 2024-10-03 11:17:00

Android系统中的进程管理:进程的创建的相关文章

opengl-OpenGL 在Android系统中的显示问题

问题描述 OpenGL 在Android系统中的显示问题 openGL在android系统中只能全屏显示吗?可以控制让它只在屏幕的某一个部分显示吗

Android 系统中 Location Service 的实现与架构

前言 定位服务是移动设备上最常用的功能之一,下文以 Android 源码为基础,详细分析了 Android 系统中定 位服务的架构和实现.定位服务是 Android 系统提供的一项系统服务,在 Android 系统中,所有系统服务 的架构都是类似的.只要明白其中一个,然后再去理解其他是很容易的.对于 Android 的应用开发人员来说 ,本文可以帮助他们了解他们所使用的 API 背后的实现.对于 Android 的系统开发人员来说,本文可以帮 助他们更好的了解 Android 系统架构.关于如何

如何在android系统中实现pkcs11,或者有什么可用的开源类库?

问题描述 如何在android系统中实现pkcs11,或者有什么可用的开源类库? 如何在android系统中实现pkcs11,或者有什么可用的开源类库? 解决方案 无法实现 Sun==Oracle => copying bad :)而且更严重的是,在android中没法用,以为没有能够支持的标准PKCS#11(尽管JB确实用一个专用的PKCS#11提供一些东西).并不确定是否代码是在OpenJDK,但是如果是的话,你可以试着移植.但是那基本是不可能的.因为你需要完整的PKCS#11 API,对于

在android系统中如何播放、暂停、停止歌曲?

问题描述 在android系统中如何播放.暂停.停止歌曲? 我在程序中设置了播放.暂停.停止三个按钮.当我点击播放按钮,这个按钮就消失了,显示的是暂停按钮.反之亦然.当我点击播放按钮时,程序不出错.再点击暂停按钮时,就会出错.贴出代码: package com.mpIlango; import java.io.IOException; import java.util.ArrayList; import android.app.Activity; import android.media.Med

Android系统中设置TextView的行间距(非行高)

Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacingMultiplier. 关于Android下TextView中文换行问题,可查看Android自定义view-文本自动换行. 1.android:lineSpacingExtra 设置行间距,如"3dp". 2.android:lineSpacingMultiplier 设置行间距的倍数

在android系统中如何监控可写入的控件获得焦点这样的事件

问题描述 在android系统中如何监控可写入的控件获得焦点这样的事件 在写一个手机监控程序的时候发现,需要监控用户的可输入状态.不知道有没有大神能帮忙提供些思路.这是个自主的监控程序,将会在android模拟器中运行,用作与主机进行通信.不是在真正在手机中运行的木马. 初始想法是枚举所有的窗口,然后找出哪一个窗口获得焦点,并判断此窗口是否有edit属性,嗯,PC上应该就是这样做到吧,键盘勾子是不行的,原因是不知道当前是否可输入状态.只不过在android中实在不知道该怎么做,另外,枚举的缺陷是

ios-iOS和Android系统中的微信分身版软件是如何实现的?

问题描述 iOS和Android系统中的微信分身版软件是如何实现的? 如题,微信同时只能启动一个实例,而分身版微信可以同时启动很多个实例,我想知道这是怎么做到的,其中原理是什么? 解决方案 觉得应该是从ART vm下手.猜测,是不是在精简一个小型vm来启动另一个APk. 解决方案二: Android平台上主要借助了系统的多账户机制,相当于在手机中建立了一个"虚拟机",就像是手机中的"第二系统",在其中运行的应用不会对原手机系统产生任何干扰,保障了两个账户的同时独立运

Android系统中 ActivityManager 是如何绑定系统的后台服务的?

问题描述 Android系统中 ActivityManager 是如何绑定系统的后台服务的? Android系统中 ActivityManager 是如何绑定系统的后台服务的? 解决方案 建议你去看下Android源代码.还有老罗那本书对这个有介绍! 解决方案二: binder,用aidl写的那个

如何从网络服务器中下载数据及针对数据操作的方法到android系统中并执行?

问题描述 如何从网络服务器中下载数据及针对数据操作的方法到android系统中并执行? 有几千组数据和针对数据操作的方法,每组的数据和方法都不相同.每次仅需下载其中的几组.该方法要在android上执行,不知如何实现? 如果用SQLite数据库存贮数据,触发器来实现针对数据操作的方法,android只需从SQLite数据库中取数据.但这样一方面担心某些方法太复杂,触发器实现不了.另一方面担心响应速度过慢. 不知android下可否把不同的代码封装成windows下的DLL文件一样?这样需要哪个就