简介:

Android中,Zygote是整个Android系统的核心进程,是Android系统的心脏。所有的Android应用程序,包括Android框架层所在的进程system_server,都是由Zygote孵化(通过Linux系统调用fork函数创建)出来的。

Zygote初探:

我们说,zygote是整个Android系统的心脏,在zygote被启动的同时,还启动了其它的很多守护进程,有的比zygote启动的还早。 换句话说,在zygote还没有启动时,其实,作为底层的Linux系统已经启动了,标志就是init进程已经启动。

如果我们在adb shell命令行,用kill命令(在root的情况下),居然可以杀死zygote,然后,设备屏幕又会显示“>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<”,即android系统重启。

zytote是一个实实在在的进程,可以在进程列表中查看到:

USER     PID   PPID  VSIZE RSS   WCHAN    PC         NAME

root     1     0     548   196   c00b8c14 0000d5cc S /init

root     2     0     0     0     c006bf70 00000000 S kthreadd

......

root     724   2     0     0     c0216908 00000000 S mmcqd

root     726   1     772   180   c019dbc4 afe0c1dc S /system/bin/sh

system   727   1     840   188   c022d8a0 afe0c47c S /system/bin/servicemanager

......

root     734   1     72000 14172 c00b92b0 afe0c5a4 S zygote
......

system   825   734   574128 28360 ffffffff afe0c47c S system_server
......

app_22   890   734   117068 30228 ffffffff afe0d404 S oms.home

可以看到,

zygote的父进程id是1,即init进程,而且,zygote的权限是root权限;

system_server是Android系统框架所在的进程,即AMS,WMS等很多服务所在的就是这个进程。system_server的父进程就是zygote;

oms.home:是home应用,即手机桌面应用。oms是Ophone系统(中国移动基于Android系统进行定制的一个系统)。作为应用程序,它的父进程也是zygote。

下图,是比较重要的一些进程的相关关系:

zygote的启动流程简单说明:

1)创建Java虚拟机;
2)为Java虚拟机注册native方法;
3)在com.android.internal.os.ZygoteInit中调用java类的主要方法;
4)加载ZygoteInit class;
5)注册zygote socket;
6)加载preload class;
7)加载preload 资源文件;
8)调用Zygote::forkSystemServer,fork一个新的进程,调用SystemServer的main方法,从而进入到java层的system_server进程的初始化流程中;

zygote进程初始化源代码分析:

代码位置:“frameworks/base/core/java/com/android/internal/os/

zygote进程是由init.rc文件中启动的,如下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd

app_process:

其中app_process被编译成一个可执行程序,

代码位置:frameworks\base\cmds\app_process,分析如下:

1)Android.mk:

Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)LOCAL_SRC_FILES:= \app_main.cppLOCAL_SHARED_LIBRARIES := \libcutils \libutils \libandroid_runtimeLOCAL_MODULE:= app_processinclude $(BUILD_EXECUTABLE)

其中,app_main.cpp是入口,而且,引用了libandroid_runtime库。

2)app_main.cpp:

看一下app_main.cpp的main函数:

int main(int argc, const char* const argv[])
{// These are global variables in ProcessState.cppmArgC = argc;mArgV = argv;mArgLen = 0;for (int i=0; i<argc; i++) {mArgLen += strlen(argv[i]) + 1;}mArgLen--;AppRuntime runtime;const char* argv0 = argv[0];// Process command line arguments// ignore argv[0]argc--;argv++;// Everything up to '--' or first non '-' arg goes to the vmint i = runtime.addVmArguments(argc, argv);// Parse runtime arguments.  Stop at first unrecognized option.bool zygote = false;bool startSystemServer = false;bool application = false;const char* parentDir = NULL;const char* niceName = NULL;const char* className = NULL;while (i < argc) {const char* arg = argv[i++];if (!parentDir) {parentDir = arg;} else if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = "zygote";} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true;} else if (strcmp(arg, "--application") == 0) {application = true;} else if (strncmp(arg, "--nice-name=", 12) == 0) {niceName = arg + 12;} else {className = arg;break;}}if (niceName && *niceName) {setArgv0(argv0, niceName);set_process_name(niceName);}runtime.mParentDir = parentDir;if (zygote) {runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");} else if (className) {// Remainder of args get passed to startup class main()runtime.mClassName = className;runtime.mArgC = argc - i;runtime.mArgV = argv + i;runtime.start("com.android.internal.os.RuntimeInit",application ? "application" : "tool");} 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)根据输入参数来判断,该如何进行runtime.start参数的配置。在上面的initl.rc中,参数是:

-Xzygote /system/bin --zygote --start-system-server

所以 ,有:

zygote = true;

startSystemServer = true;

然后,会执行到:

runtime.start("com.android.internal.os.ZygoteInit",
        startSystemServer ? "start-system-server" : "");

去通过ZygoteInit来继续进行zygote的初始化流程。

3)runtime:

既然ZygoteIni由truntime.start来运行,看一下runtime的实现:

类图:

流程图:

分析:

如果是“--zygote”,则启动zygote进程相关代码;

否则,会根据参数,启动(创建)参数所在的app。

4)ZygoteInit:

在分析完runtime之后,再来看一runtime.start的第一个参数“

com.android.internal.os.ZygoteInit

”的相关实现:

代码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。

这是个java代码,也就是说,执行了大半天,这时候终于执行到了java代码,有runtime(即dvm虚拟机的runtime运行时库)启动了java代码。看一下这个目录的代码文件(已经是java代码了):

在这个目录下,没有Android.mk文件。这是因为这已经是java层了,而不是native层。对于java层的代码来说,只是说是不是要打包到jar中。而对于C/C++来说,要编译成lib,或者exe。

其中,ZygoteInit的 流程图如下:

分析:

(1)为zygote注册一个socket,并且保存起来,保存到

sServerSocket 
变量中;这是一个LocalServerSocket类型的socket,详细代码如下:

private static void registerZygoteSocket() {if (sServerSocket == null) {int fileDesc;try {String env = System.getenv(ANDROID_SOCKET_ENV);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException(ANDROID_SOCKET_ENV + " unset or invalid", ex);}try {sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));} catch (IOException ex) {throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);}}}

同时,创建了文件描述符FileDescriptor, 即ANDROID_SOCKET_ENV环境变量对应的文件描述符FileDescriptor,ANDROID_SOCKET_ENV的定义:

private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
(2)预加载一些class和资源文件。这样的好处是,会加快app的启动。当一个app启动时,就不需要重新加载这些资源了;

(3)孵化(fork)SystemServer进程:Zygote::SystemServer就会通过系统调用fork函数来创建一个新的进程,这个进程就是SystemServer;

(4)然后,执行到SystemServer的main方法,这是一个java类,整个SystemServer的文件中,定义了两个类,如下:

 5) SystemServer:

在SystemServer.main方法中,

System.loadLibrary("android_servers"); //加载“android_servers”库
init1(args); //这是个jni接口,会再调用到native层的init1方法中。

然后,init1会执行到native层,然后再通过native层调用到java层的init2方法,相关代码流程:

SystemServer.java -> com_android_server_SystemServer.cpp -> system_init.cpp ->SystemServer.java

com_android_server_SystemServer.cpp的init1函数:

static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{system_init();
}
system_init的实现(在system_init.cpp文件中):extern "C" status_t system_init()
{ALOGI("Entered system_init()");sp<ProcessState> proc(ProcessState::self());sp<IServiceManager> sm = defaultServiceManager();ALOGI("ServiceManager: %p\n", sm.get());sp<GrimReaper> grim = new GrimReaper();sm->asBinder()->linkToDeath(grim, grim.get(), 0);char propBuf[PROPERTY_VALUE_MAX];property_get("system_init.startsurfaceflinger", propBuf, "1");if (strcmp(propBuf, "1") == 0) {// Start the SurfaceFlingerSurfaceFlinger::instantiate();}property_get("system_init.startsensorservice", propBuf, "1");if (strcmp(propBuf, "1") == 0) {// Start the sensor serviceSensorService::instantiate();}// And now start the Android runtime.  We have to do this bit// of nastiness because the Android runtime initialization requires// some of the core system services to already be started.// All other servers should just start the Android runtime at// the beginning of their processes's main(), before calling// the init function.ALOGI("System server: starting Android runtime.\n");AndroidRuntime* runtime = AndroidRuntime::getRuntime();ALOGI("System server: starting Android services.\n");JNIEnv* env = runtime->getJNIEnv();if (env == NULL) {return UNKNOWN_ERROR;}jclass clazz = env->FindClass("com/android/server/SystemServer");if (clazz == NULL) {return UNKNOWN_ERROR;}jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");if (methodId == NULL) {return UNKNOWN_ERROR;}env->CallStaticVoidMethod(clazz, methodId);ALOGI("System server: entering thread pool.\n");ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();ALOGI("System server: exiting thread pool.\n");return NO_ERROR;
}

分析:

在init1函数,启动一写service(如果没有启动的话);然后,创建一个runtime,由runtime去调用到java层的SystemServer类的init2方法;最后,将其加入线程池。

那好,我嗯再回到SystemServer类的init2方法,如下:

public static final void init2() {Slog.i(TAG, "Entered the Android system server!");Thread thr = new ServerThread();thr.setName("android.server.ServerThread");thr.start();}

在init2中,启动了ServerThread。

6)ServerThread:

所以,整个SystemServer其实,最关键的实体是这个ServerThread线程。我们之间看run函数的实现:

@Overridepublic void run() {Looper.prepare();android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);BinderInternal.disableBackgroundScheduling(true);android.os.Process.setCanSelfBackground(false);LightsService lights = null;PowerManagerService power = null;BatteryService battery = null;VibratorService vibrator = null;AlarmManagerService alarm = null;NetworkManagementService networkManagement = null;NetworkStatsService networkStats = null;NetworkPolicyManagerService networkPolicy = null;ConnectivityService connectivity = null;......// Critical services...try {Slog.i(TAG, "Entropy Mixer");ServiceManager.addService("entropy", new EntropyMixer());Slog.i(TAG, "Power Manager");power = new PowerManagerService();ServiceManager.addService(Context.POWER_SERVICE, power);......pm = PackageManagerService.main(context,factoryTest != SystemServer.FACTORY_TEST_OFF,onlyCore);boolean firstBoot = false;try {firstBoot = pm.isFirstBoot();} catch (RemoteException e) {}ActivityManagerService.setSystemProcess();mContentResolver = context.getContentResolver();// The AccountManager must come before the ContentServicetry {Slog.i(TAG, "Account Manager");ServiceManager.addService(Context.ACCOUNT_SERVICE,new AccountManagerService(context));} catch (Throwable e) {Slog.e(TAG, "Failure starting Account Manager", e);}......} catch (RuntimeException e) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting core service", e);}DevicePolicyManagerService devicePolicy = null;StatusBarManagerService statusBar = null;InputMethodManagerService imm = null;AppWidgetService appWidget = null;NotificationManagerService notification = null;WallpaperManagerService wallpaper = null;LocationManagerService location = null;CountryDetectorService countryDetector = null;TextServicesManagerService tsms = null;LockSettingsService lockSettings = null;DreamManagerService dreamy = null;// Bring up services needed for UI.if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {try {Slog.i(TAG, "Input Method Service");imm = new InputMethodManagerService(context, wm);ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);} catch (Throwable e) {reportWtf("starting Input Manager Service", e);}try {Slog.i(TAG, "Accessibility Manager");ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,new AccessibilityManagerService(context));} catch (Throwable e) {reportWtf("starting Accessibility Manager", e);}}try {wm.displayReady();} catch (Throwable e) {reportWtf("making display ready", e);}try {pm.performBootDexOpt();} catch (Throwable e) {reportWtf("performing boot dexopt", e);}try {ActivityManagerNative.getDefault().showBootMessage(context.getResources().getText(com.android.internal.R.string.android_upgrading_starting_apps),false);} catch (RemoteException e) {}if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {MountService mountService = null;if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {try {/** NotificationManagerService is dependant on MountService,* (for media / usb notifications) so we must start MountService first.*/Slog.i(TAG, "Mount Service");mountService = new MountService(context);ServiceManager.addService("mount", mountService);} catch (Throwable e) {reportWtf("starting Mount Service", e);}}try {Slog.i(TAG,  "LockSettingsService");lockSettings = new LockSettingsService(context);ServiceManager.addService("lock_settings", lockSettings);} catch (Throwable e) {reportWtf("starting LockSettingsService service", e);}try {Slog.i(TAG, "Device Policy");devicePolicy = new DevicePolicyManagerService(context);ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);} catch (Throwable e) {reportWtf("starting DevicePolicyService", e);}......}// These are needed to propagate to the runnable below.final Context contextF = context;final BatteryService batteryF = battery;final NetworkManagementService networkManagementF = networkManagement;final NetworkStatsService networkStatsF = networkStats;final NetworkPolicyManagerService networkPolicyF = networkPolicy;final ConnectivityService connectivityF = connectivity;final DockObserver dockF = dock;final UsbService usbF = usb;......Looper.loop();Slog.d(TAG, "System ServerThread is exiting!");}

说明:

在这个run方法中,初始化了Android系统框架层的各种service,包括:

PowerManagerService:电源管理服务

BatteryService:电池服务

PackageManagerService:包管理服务

ActivityManagerService:activity管理服务

NetworkStatsService:网络状态服务

......

这样,Android系统框架层的SystemServer进程启动完毕,许多srevice组件也都初始化好了。

至此,整个zygote就完成了它的使命,最终把Android系统框架层的SystemServer进程启动完毕做为结束点。

7)runSelectLoopMode函数:

在初始化完的SystemServer进程后,就进入一个循环中,即runSelectLoopMode函数的执行。等待客户端的请求事件,如果有请求事件,就去创建进程,这就涉及到应用进程的创建了,这部分内容在下一节讨论。

下一节:

Android系统的心脏-Zygote进程如何fork一个新的应用进程


Android系统的心脏-Zygote进程启动流程分析相关推荐

  1. Zygote进程启动流程分析

    文中的源代码版本为api23 Zygote进程启动流程分析 先说结论,zygote进程启动过程中主要做了下面这些事情: 启动DVM虚拟机 预加载部分资源,如一些通用类.通用资源.共享库等 启动syst ...

  2. 【Android 逆向】修改运行中的 Android 进程的内存数据 ( Android 系统中调试器进程内存流程 | 编译内存调试动态库以及调试程序 )

    文章目录 一.Android 系统中调试器进程内存流程 二.编译内存调试动态库以及调试程序 三.博客资源 一.Android 系统中调试器进程内存流程 修改游戏运行中的内存 , 游戏运行之后 , 游戏 ...

  3. Android系统10 RK3399 init进程启动(三十八) 属性Selinux实战编程

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 上一节 ...

  4. 【Android】系统启动流程(zygote 进程启动流程)

    前言 先上图,大致了解一下 Android 设备点击电源键开机到创建出 system_server 进程的流程, 里面细化的子流程和 system_server 之后发生的事情我将会在后续的文章中详细 ...

  5. Android系统10 RK3399 init进程启动(三十五) 属性文件介绍和生成过程

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 ini ...

  6. Android系统10 RK3399 init进程启动(三十四) 常见Property属性

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 上一节 ...

  7. Android系统10 RK3399 init进程启动(三十三) property属性系统框架

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 属性系 ...

  8. Android系统10 RK3399 init进程启动(三十六) 属性property操作API

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 前面几 ...

  9. Android系统10 RK3399 init进程启动(十八) isLoggable日志级别输出控制

    配套系列教学视频链接: 安卓系列教程之ROM系统开发-百问100ask 说明 系统:Android10.0 设备: FireFly RK3399 (ROC-RK3399-PC-PLUS) 前言 在编写 ...

最新文章

  1. 获取执行SQL语句的返回结果
  2. Servlert接口的doGet()、doPst()方法
  3. 多租户数据中心该如何布线?
  4. 2012.9华为软件开发面试题
  5. 学习编程技术常见的疑问,你敢说你没有过一个吗?信你个鬼!
  6. Hbase 实现微博好友关注功能
  7. kafka python_kafka python
  8. mysql foreign key_MYSQL外键(Foreign Key)的使用
  9. 服务器端性能优化之CDN
  10. 20135337——信息安全设计基础第十四周学习笔记
  11. 受力分析软件_大赛作品 | 关于Z型路灯受力情况分析
  12. win7纯净版系统哪里下载好
  13. oracle lsnrctl status unknown,理解 oracle 的 lsnrctl status
  14. 对数正态随机数c语言程序,对数正态随机数
  15. Educational Codeforces Round 61 (Rated for Div. 2)(A、B、C、D、E、F)
  16. 光敏电阻5506主要参数_常用光敏电阻参数表
  17. npm 清理vue项目缓存
  18. iperf 工具使用
  19. 2022.1.17学习总结
  20. 现货黄金走势图怎么看?

热门文章

  1. Oracle日期型函数详解
  2. InteliJ IDEA2018.2.1X64 破解 使用
  3. Jquery获取被选中的复选框的value值
  4. C语言的编译过程常见的错误和警告
  5. 微前端 - micro-app 数据通信
  6. python之拉格朗日插值算法完成计算
  7. jsp+ssm计算机毕业设计电影影评网【附源码】
  8. FPA软件评估方法论
  9. 【概念辨析】二维数组传参的几种可能性
  10. 电商数仓:用户行为数据仓库(一)数据仓库建设和技术选型