本文主要分析了当前热门手机平台android系统的进程创建分析。先简单介绍android的技术架构,然后概述android启动新程序的整体流程,接着详细分析程序启动中的进程创建。在分析中辅以代码解析,从而让读者能较为清晰的了解到android时如何通过进程创建来启动新程序的。

Android架构

android是世界上最受欢迎的手机平台。它以linux为基础,辅以定制的C语言本地库和内嵌独有的Dalvik虚拟机的Android runtime环境。在此基础上,用java构建了大量丰富的android framework,为最上层用户application的构建提供了极大的便利和强大的功能支持。这样,开发人员可以用java语言,开发运行于Dalvik虚拟机上的应用程序,降低开发成本。

下面是android的技术架构图。

由此可见,android的运行最终离不开linux,其底层原理也是和linux一致的。所以,android的内核进程的创建也必定和linux内核的进程创建有紧密联系,但在分析android进程创建之前,先了解下android在application和framework层是怎么创建新程序的。

Android 启动新程序

在java语言为基础的application层,android涉及的概念和linux相差甚远,简单说下几个重要的概念:

ActivityThread类:该类为应用程序的主线程类,所有的应用程序都有且仅有一个ActivityThread类,程序的入口为该类中的static main()函数。

Activity类:该类为APK(AndroidPackage,是一种通过AndroidSDK编译的工程打包成的安装程序文件)程序的一个最小运行单元,一个APK程序中可以包含多个Activity对象,ActivityThread主类会根据用户操作选择运行哪个Activity对象。

ActivityManagerService类:简称AMS,它的作用是管理所有应用程序中的Activity。

具体过程如下;

1.直接调用 startActivity()启动指定的 Activity。AmS 收到客户请求 startActivity()后,会首先暂停当前的 Activity

2.当 A 进程完成暂停后,报告AmS,AmS判断需要运行的目标Activity是否已存在,如果存在则直接恢复执行而不需要创建新程序

3.如果第二步中AmS检查到目标Activity不存在,则启动对应进程。

a)AmS调用Process进程类启动一个新的应用进程

b)新的应用进程会从ActivityThread 的 main()函数处开始执行,当目标进程启动后,再报告AmS 自己已经启动

c)AmS 再通知目标进程启动目标Activity。

这样,经过了第三步后,目标activity就这样在新的进程上运行了。

上面从用户应用程序的角度分析了android程序如何启动新程序。下面分析下其如何调用底层创建新进程的方法。

Framework创建新进程

对于应用程序的创建,最终通过ams调度Process.start()静态方法来启动新程序:

[java] view plain copy
  1. //在ActivityManagerService.java中:
  2. Process.ProcessStartResultstartResult=Process.start("android.app.ActivityThread",
  3. app.processName,uid,uid,gids,debugFlags,
  4. app.info.targetSdkVersion,null,null);

上面的函数参数说明将会在新程序(进程)中调用android.app.ActivityThread类,实际上最终将调用其main函数。

Process.start()内部又继续调用Process类的静态函数startViaZygote()来进行创建进程的命令发送。为什么说是命令发送呢,查看startViaZygote()函数最后一行:

[java] view plain copy
  1. returnzygoteSendArgsAndGetResult(argsForZygote);

zygoteSendArgsAndGetResult函数最终实现的,是向socket服务端写数据,把创建进程的请求通过socket通讯方式来让framework的进程孵化类zygote创建新进程。而数据就是argsForZygote——一个以字符串List形式的把Process.start()所有调用参数都包含在里面的变量。其过程如下图所示:


至于为什么是通过socket来发送创建进程的命令,其创建过程是怎样的?而又如何和linux联系的?下面将分析Android进程孵化环境,来回答上面的问题。


Android进程孵化环境

当Android内核启动后,此时系统的状态和普通的Linux系统基本相同,通过配置Android中的init.rc文件,可以指定内核启动后都要执行什么程序,而在此配置文件中指定的之后所要启动的程序才是Android系统和普通Linux应用系统的区别。Android系统里init.rc中所启动的一个重要进程被称作zygote进程,也称为“种子进程”,从进程的角度来看,种子进程仅仅是一个Linux进程而已,它和一个只包含main()函数的C程序所产生的进程是同一个级别,但种子进程里面所运行的程序基本上就是Android内核的精华所在,其内部主要完成了两件事情。第一件事情是装载了一段程序代码,这些代码都是用C语言写的,这段代码的作用只是为了能够执行Java编译器编译出的字节码,功能类似Java虚拟机,在Android中称为Dalvik虚拟机。第二件事情必须基于第一件事情之后,即当Dalvik虚拟机代码初始化完成后,开始执行ZygoteInit.java类中的main()函数。ZygoteInit.java这个Jar包的目录位置信息也是在init.rc中进行配置的,是使用一个“zygote”标志符,Dalvik虚拟机就会从init.rc配置项的键值对中得到ZygoteInit类所在的Jar包,而这个Jar包正是Android的另一个核心--framework.jar。

接下ZygoteInit类中main()函数所做的事情和Linux本身就没多大关系了,该main()函数中才刚刚开始启动Android的核心功能。首先加载一些类文件,这些类将作为以后所有其它Apk程序共享的类,接着,会创建一个Socket服务端,该服务端将用于通过Socket启动新进程。zygote进程被称为“种子”进程的原因就是,当其内部的Socket服务端收到启动新的Apk进程的请求时,会使用Linux的一个系统调用folk()函数从自身复制出一个新的进程,新进程和Zygote进程将共享已经装载的类,这些类都是在framework.jar中定义的。

Zygote进程、SystemServer进程、各APK进程和创建进程的socket服务端/客户端的关系如下图所示:


[java] view plain copy
  1. //ZygoteInit.java的main函数如下:
  2. publicstaticvoidmain(Stringargv[]){
  3. try{
  4. registerZygoteSocket();//注册一个socketserver来监听zygote命令
  5. preloadClasses();//预加载javaclass
  6. preloadResources();//预加载资源文件
  7. gc();/*初始化GC垃圾回收机制*/
  8. if(argv[1].equals("true")){
  9. /*通过main中传递过来的第二个参数startsystemserver=”true”启动systemserver,在startSystemServer()中会fork一个新的进程命名为system_server,执行的是com.android.server包中的SystemServer.java文件中的main函数*/
  10. startSystemServer();///*************
  11. }elseif(…)
  12. if(ZYGOTE_FORK_MODE){
  13. runForkMode();/*将进入Zygote的子进程*/
  14. }else{
  15. runSelectLoopMode();/*Zygote进程进入无限循环,不再返回。接下来的zygote将会作为一个孵化服务进程来运行。*/
  16. }
  17. closeServerSocket();
  18. }
  19. }
[java] view plain copy
  1. //com.android.server包中的SystemServer.java核心代码如下:
  2. publicstaticvoidmain(String[]args){
  3. System.loadLibrary("android_servers");//libandroid_servers是由目录frameworks/base/services/jni下的源码编译所得
  4. init1(args);//init1实际上是一个jni本地接口
  5. }
  6. staticvoidandroid_server_SystemServer_init1(JNIEnv*env,jobjectclazz){
  7. //init1接口主要调用一个系统初始化方法
  8. system_init();
  9. }
[cpp] view plain copy
  1. //JNI的实际调用c函数:
  2. extern"C"status_tsystem_init(){
  3. charpropBuf[PROPERTY_VALUE_MAX];
  4. property_get("system_init.startsurfaceflinger",propBuf,"1");
  5. if(strcmp(propBuf,"1")==0){
  6. //启动SurfaceFlinger
  7. SurfaceFlinger::instantiate();
  8. }
  9. if(!proc->supportsProcesses()){
  10. //启动CameraService
  11. CameraService::instantiate();
  12. //启动AudioPolicyService
  13. AudioPolicyService::instantiate();
  14. }
  15. AndroidRuntime*runtime=AndroidRuntime::getRuntime();
  16. //执行com.android.server.SystemServer类的init2函数,主要负责开启一个ServerThread线程
  17. runtime->callStatic("com/android/server/SystemServer","init2")
  18. }
[java] view plain copy
  1. //JNI回调SystemServer.java的init2()函数
  2. publicstaticfinalvoidinit2(){
  3. Threadthr=newServerThread();
  4. thr.setName("android.server.ServerThread");
  5. thr.start();
  6. }
  7. //ServerThread线程的run函数会启动系统中绝大部分的androidservice,并最后进入Loop.loop(),,,,(SystemServer.java)
  8. publicvoidrun(){
  9. try{
  10. Slog.i(TAG,"PowerManager");
  11. power=newPowerManagerService();
  12. ServiceManager.addService(Context.POWER_SERVICE,power);
  13. Slog.i(TAG,"ActivityManager");
  14. context=ActivityManagerService.main(factoryTest);
  15. Slog.i(TAG,"PackageManager");
  16. pm=PackageManagerService.main(context,
  17. factoryTest!=SystemServer.FACTORY_TEST_OFF);
  18. Slog.i(TAG,"ContentManager");
  19. ContentService.main(context,
  20. factoryTest==SystemServer.FACTORY_TEST_LOW_LEVEL);
  21. Slog.i(TAG,"BatteryService");
  22. battery=newBatteryService(context);
  23. ServiceManager.addService("battery",battery);
  24. //其余addservice的过程类似,只是启动的不同服务罢了,后面还启动了很多服务,如:Lights、Vibrator、Alarm、Sensor、Bluetooth、InputMethod、NetStat、NetworkManagement、Connectivity、Mount、Notification、Audio等。在这些服务都启动完了之后,就是使用xxx.systemReady()通知各个服务,系统已经就绪。
  25. publicvoidrun(){
  26. if(batteryF!=null)batteryF.systemReady();
  27. if(connectivityF!=null)connectivityF.systemReady();
  28. if(dockF!=null)dockF.systemReady();
  29. if(uiModeF!=null)uiModeF.systemReady();
  30. if(recognitionF!=null)recognitionF.systemReady();
  31. Watchdog.getInstance().start();
  32. }
  33. });
  34. Looper.loop();//Runthemessagequeueinthisthread。
  35. }


小结

再从头梳理下android程序创建的整个流程:application层的程序发起创建应用程序的命令->Ams调度框架通过framework发起socket通讯通知新进程创建->zygote孵化进程接收socket信息并调用内核创建新进程。这样,这个流程就串起来了。

综上所述,创建程序新进程的任务最关键就是zygote进程。Zygote进程起到一个承上启下的作用。对于framework,zygote进程接收上层应用通过socket发送过来的新进程创建命令,对于kernel而言,zygote进程主要调用了内核的fork()系统调用来进行新进程的创建,所以zygote在android系统中扮演一个非常重要的角色,是新进程创建的一个孵化器。

至此,本文也通过代码和相关流程解释了为什么android程序进行最终还是建立在linux基础之上。


参考资料:

1 android.googlesource.com

2 柯元旦《android内核剖析》电子工业出版社

3 韩超,梁泉《android系统原理及开发要点详解》电子工业出版社

4 Google IO 《Android Anatomy and Physiology》

5 Robert Love《Linux.Kernel.Development.2nd.Edition》Novell Press

更多相关文章

  1. Android(安卓)系统log抓取,实现原理分析
  2. android init进程说明
  3. android Manifest.xml全局配置文件中根标签中package属性及标签
  4. 集成Flutter混合开发(入坑篇)
  5. Android应用启动后自动创建桌面快捷方式
  6. Android应用启动后自动创建桌面快捷方式
  7. Android之应用进程托管
  8. Android广播机制详解
  9. [Android]如何做一个崩溃率少于千分之三噶应用app(6)-动态创建

随机推荐

  1. android camera 2
  2. DRM in Android
  3. Android(安卓)数字签名学习笔记
  4. Android智能指针SP WP使用方法介绍
  5. Android深入浅出之Audio 第一部分 AudioT
  6. Android(安卓)数字签名
  7. 将服务器端字符读取至android的文本控件,
  8. android 自适应 多屏幕支持 --Android多
  9. android:maxHeight,android:maxWidth失效
  10. 在英特尔® 架构平台上开发和优化基于 ND