init进程
Android系统所有进程的祖先,是Android系统内核初始化完毕后,进入用户空间启动的第一个进程。
Android虚拟机
Dalvik虚拟机是谷歌自己设计的用于Android平台的虚拟机。Android4.4同时提供了Dalvik和ART虚拟机。Android5.0以后,Dalvik虚拟机彻底被删除,ART虚拟机取而代之。
Zygote
中文翻译为“受精卵、结合子”
Zygote是Android系统中,负责孵化所有其他应用进程的一个进程,Android系统是基于Linux内核的系统,所以Zygote进程是由Linux启动的用户级init进程创建的,Zygote是init进程的子进程,Zygote是一个java进程,负责启动Android虚拟机(Dalvik、ART)。
BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。
Kernel指的是操作系统内核Linux初始化及启动。
init进程是Android内核初始化之后创建并启动的第一个进程,是所有进程的父进程,init进程首先调用/system/core/init/init.cpp(点击链接查看源码)的main方法,该方法做了两件事:
(1),搭建系统运行环境,创建相关目录,设置相关路径和属性;
(2),解析rc配置文件,执行rc配置文件所要求的动作和命令
init.cpp的main方法中其中有一句代码parser.ParseConfig("/init.rc");用来读取rc配置并执行init.rc位于/system/core/rootdir/init.rc(点击链接查看源码)
7 import /init.environ.rc
8 import /system/etc/init/hw/init.usb.rc
9 import /init.${ro.hardware}.rc
10 import /vendor/etc/init/hw/init.${ro.hardware}.rc
11 import /system/etc/init/hw/init.usb.configfs.rc
12 import /system/etc/init/hw/init.${ro.zygote}.rc
...
946 # It is recommended to put unnecessary data/ initialization from post-fs-data
947 # to start-zygote in device's init.rc to unblock zygote start.
948 on zygote-start && property:ro.crypto.state=unencrypted
949 wait_for_prop odsign.verification.done 1
950 # A/B update verifier that marks a successful boot.
951 exec_start update_verifier_nonencrypted
952 start statsd
953 start netd
954 start zygote
955 start zygote_secondary
956
957 on zygote-start && property:ro.crypto.state=unsupported
958 wait_for_prop odsign.verification.done 1
959 # A/B update verifier that marks a successful boot.
960 exec_start update_verifier_nonencrypted
961 start statsd
962 start netd
963 start zygote
964 start zygote_secondary
965
966 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
967 wait_for_prop odsign.verification.done 1
968 # A/B update verifier that marks a successful boot.
969 exec_start update_verifier_nonencrypted
970 start statsd
971 start netd
972 start zygote
973 start zygote_secondary
/init.${ro.zygote}.rc会根据硬件实际的配置,选择导入32位还是64位。在Android12上有这几个选择:init.zygote32.rc,init.zygote64.rc,init.zygote64_32.rc(点击链接查看源码)
start zygote是启动Zygote服务的方式,所以Zygote服务就会被启动
Zygote服务就是下面配置文件中的服务【service zygote】
比如设备是64位的,则init启动的就是/system/core/rootdir/init.zygote64.rc(点击链接查看源码)配置文件中的【service zygote】
1 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
2 class main
3 socket zygote stream 660 root system
4 onrestart write /sys/android_power/request_state wake
5 onrestart write /sys/power/state on
6 onrestart restart audioserver
7 onrestart restart cameraserver
8 onrestart restart media
9 onrestart restart netd
10 writepid /dev/cpuset/foreground/tasks
综上所述,Zygote进程是Init进程通过解析init.rc过程中又去解析了init.zygote64.rc或者init.zygote32.rc配置文件,以Service的方式创建并启动
上面的zygote service配置中,有一个重要选项/system/bin/app_process64,通过执行app_process来进入zygote进程。
app_process主要作用是解析启动参数,然后根据启动参数选择不同的启动模式
执行 /system/bin/app_process64命令之后,程序就会执行到/frameworks/base/cmds/app_process/,该目录下面就是可执行文件,该路径下有app_main.cpp(点击链接查看源码),最终执行的就是app_main.cpp的main方法:
/system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
上面标红的是调用app_main.cpp的main()方法的入参,使用中间的空格符切割一下,得到5个值如下:
下面的main()函数两个入参,int argc,char* const argv[],其中argc是传入参数的数目,这里应该等于5,argv是传入参数的值,就是上面这5个切割后的字符串
- int main(int argc, char* const argv[])
- {
- ...
- //argc=5
- // argv[0]="/system/bin/app_process64"
- // argv[1]="-Xzygote"
- // argv[2]="/system/bin"
- // argv[3]="--zygote"
- // argv[4]="--start-system-server"
-
- argv[0]="/system/bin/app_process64"被传入runtime
- //AppRuntime继承自AndroidRuntime,
- //这里创建AppRuntime对象,main方法的操作都是通过这个runtime完成的
- AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
- argc--;//执行此语句块后,argc=4
- argv++;//argv[0]被忽略
- // argc=4
- // argv[1]="-Xzygote"
- // argv[2]="/system/bin"
- // argv[3]="--zygote"
- // argv[4]="--start-system-server"
-
- int i;
- for (i = 0; i < argc; i++) {
- if (argv[i][0] != '-') {//很明显遍历到argv[2]="/system/bin"时候直接break
- break;
- }
- if (argv[i][1] == '-' && argv[i][2] == 0) {
- ++i; // Skip --.
- break;
- }
- //只有argv[1]="-Xzygote"会走到这一步,再往后遍历直接break了
- runtime.addOption(strdup(argv[i]));
- }
- //上一步又使用了一个参数argv[1]="-Xzygote"。忽略掉,所以代码走到这里还剩下三个参数
- // argc=3
- // argv[2]="/system/bin"
- // argv[3]="--zygote"
- // argv[4]="--start-system-server"
- bool zygote = false;
- bool startSystemServer = false;
- bool application = false;
- String8 niceName;
- String8 className;
- ++i; // Skip unused "parent dir" argument.
- while (i < argc) {
- const char* arg = argv[i++];
- if (strcmp(arg, "--zygote") == 0) {
- // argv[3]="--zygote"满足条件,zygote=true,表示当前进程是zygote
- zygote = true;
- //static const char ZYGOTE_NICE_NAME[] = "zygote64";
- //static const char ZYGOTE_NICE_NAME[] = "zygote";
- niceName = ZYGOTE_NICE_NAME;//设置niceName为zygote64或者zygote
- } else if (strcmp(arg, "--start-system-server") == 0) {
- // argv[4]="--start-system-server",这里说明需要启动System Server
- startSystemServer = true;
- } else if (strcmp(arg, "--application") == 0) {
- application = true;
- } else if (strncmp(arg, "--nice-name=", 12) == 0) {
- niceName.setTo(arg + 12);
- } else if (strncmp(arg, "--", 2) != 0) {
- className.setTo(arg);
- break;
- } else {
- --i;
- break;
- }
- }
-
- //设置后面调用ZygoteInit.java的main方法或者RuntimeInit.java的Main方法的参数
- //这里的参数先是传给了Runtime的start方法,start方法里面又将其转成Java参数的
- Vector
args; - if (!className.isEmpty()) {
- //非Zygote模式,这种情况可能是application模式或者tool模式
- args.add(application ? String8("application") : String8("tool"));
- runtime.setClassNameAndArgs(className, argc - i, argv + i);
- } else {
- //Zygote模式,这里可以证明后续调用ZygoteInit的main方法,会启动System Server服务
- if (startSystemServer) {
- args.add(String8("start-system-server"));
- }
- char prop[PROP_VALUE_MAX];
- if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
- LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
- ABI_LIST_PROPERTY);
- return 11;
- }
- String8 abiFlag("--abi-list=");
- abiFlag.append(prop);
- args.add(abiFlag);
-
- // In zygote mode, pass all remaining arguments to the zygote
- // main() method.
- for (; i < argc; ++i) {
- args.add(String8(argv[i]));
- }
- }
- //niceName在参数解析时被设置。此处变更了app_process启动的进程名为zygote。
- if (!niceName.isEmpty()) {
- runtime.setArgv0(niceName.string());
- set_process_name(niceName.string());
- }
- //runtime.start启动Android运行环境
- if (zygote) {
- //com.android.internal.os.ZygoteInit是Android Java运行时环境的初始化类,
- runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
- } else if (className) {
- //非Zygote模式,则执行RuntimeInit.java的main方法
- 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;
- }
- }
app_main.cpp的main方法,主要做了三件事儿:
app_process是c++本地程序,源码目录为 frameworks/base/cmds/app_process/
app_process是可以执行java代码的命令(因为它启动了一个java虚拟机),它有两种启动模式:
1.zygote 模式:通常情况下,在–start-system-server启动参数的配置下,app_process启动之后,直接fork system_server 子进程,拉起整个android系统,之后用来孵化apk进程
2.非zygote模式:分两种子模式
(1).application模式:这种模式是zygote 创建进程后通过shell来重新加载app_process命令再执行的
(2).tool模式:这个模式主要是用来执行调试命令(如am\pm\wm等等)
AppRuntime继承自AndroidRuntime,AndroidRuntime的start方法,我们暂且先看下它的注释吧:
启动Android运行时。这涉及到启动虚拟机并在类中调用“static void main(String[] args)”方法由“className”命名。
传递给main函数两个参数,类名和指定的选项字符串。
/frameworks/base/core/jni/AndroidRuntime.cpp(点击链接查看源码)的start方法
- void AndroidRuntime::start(const char* className, const Vector
& options, bool zygote) - {
- ...
- /* start the virtual machine */
- JniInvocation jni_invocation;
- jni_invocation.Init(NULL);
- JNIEnv* env;
- //startVm 创建、启动虚拟机,并且设置相关参数。Dalvik或者ART虚拟机
- if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
- return;
- }
- onVmCreated(env);
- /*
- *向虚拟机注册Android JNI native函数,(系统so库,用户自定义so库,加载函数等)
- */
- if (startReg(env) < 0) {
- ALOGE("Unable to register all android natives\n");
- return;
- }
-
- //给接下来要调用的java main方法准备参数
- //非常经典的在Native层创建Java层对象的操作:
- //创建一个java.lang.String的数组对象
- //并根据传入的参数对数组对象逐个元素进行赋值
- jclass stringClass;
- jobjectArray strArray;
- jstring classNameStr;
-
- stringClass = env->FindClass("java/lang/String");
- assert(stringClass != NULL);
- strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
- assert(strArray != NULL);
- classNameStr = env->NewStringUTF(className);
- assert(classNameStr != NULL);
- env->SetObjectArrayElement(strArray, 0, classNameStr);
-
- for (size_t i = 0; i < options.size(); ++i) {
- jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
- assert(optionsStr != NULL);
- env->SetObjectArrayElement(strArray, i + 1, optionsStr);
- }
-
- ....
- //找到传进来的类的main方法,比如ZygoteInit的main方法
- jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
- "([Ljava/lang/String;)V");
- if (startMeth == NULL) {
- ALOGE("JavaVM unable to find main() in '%s'\n", className);
- /* keep going */
- } else {
- //通过JNI技术调用main方法
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
-
- #if 0
- if (env->ExceptionCheck())
- threadExitUncaughtException(env);
- #endif
- }
- }
- ...
- }
综上所述,AndroidRuntime.star方法,主要做了三件事儿:
如果不考虑非Zygote模式,那么Zygote服务的启动,执行app_main.cpp的main方法
而app_main.cpp的main方法做了四件事:
下面就要分析ZygoteInit了
ZygoteInit:负责Zygote进程Java层的初始化工作
- public static void main(String argv[]) {
- //创建Zygote服务管理类,用来注册Socket监听
- ZygoteServer zygoteServer = new ZygoteServer();
- //这里主要目的是拦截创建线程,
- //调用了这句代码以后,标记着Zygote进程开始Java层的初始化工作
- //如果此时创建线程会产生错误
- ZygoteHooks.startZygoteNoThreadCreation();
- // 将Zygote设置进他自己的进程组
- try {
- //将参数pid指定进程所属的组识别码设为参数pgid指定的组识别码。
- //Os.setpgid(int pid, int pgid)
- //pid=0表示设置当前进程所在的组的进程组pgid
- //pgid=0表示当前进程的PID为进程组pgid
- Os.setpgid(0, 0);
- } catch (ErrnoException ex) {
- throw new RuntimeException("Failed to setpgid(0,0)", ex);
- }
- final Runnable caller;
- try {
- // Report Zygote start time to tron unless it is a runtime restart
-
- ...日志打印
-
- //启动DDMS虚拟机监控调试服务
- RuntimeInit.enableDdms();
- //参数解析
- boolean startSystemServer = false;
- String socketName = "zygote";
- String abiList = null;
- boolean enableLazyPreload = false;
- for (int i = 1; i < argv.length; i++) {
- if ("start-system-server".equals(argv[i])) {
- //开启系统服务,这个参数是传进来的
- startSystemServer = true;
- } else if ("--enable-lazy-preload".equals(argv[i])) {
- enableLazyPreload = true;
- } else if (argv[i].startsWith(ABI_LIST_ARG)) {
- //abi类型,"--abi-list="这个参数也是传经来的
- abiList = argv[i].substring(ABI_LIST_ARG.length());
- } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
- //解析Socket name
- socketName = argv[i].substring(SOCKET_NAME_ARG.length());
- } else {//未知参数
- throw new RuntimeException("Unknown command line argument: " + argv[i]);
- }
- }
- //没有指定ABI参数会抛异常
- if (abiList == null) {
- throw new RuntimeException("No ABI list supplied.");
- }
- //注册Zygote的Socket服务端,用来监听接收启动应用程序的消息,这里的IPC不是Binder通信
- zygoteServer.registerServerSocketFromEnv(socketName);
- // In some configurations, we avoid preloading resources and classes eagerly.
- // In such cases, we will preload things prior to our first fork.
- if (!enableLazyPreload) {//没有延迟加载
- ...
- //执行预加载操作,包括系统预加载类,FrameWork资源,OpenGL资源
- preload(bootTimingsTraceLog);
- ...
- } else {//有延迟加载
- //重置线程优先级,设置为默认的Thread.NORM_PRIORITY
- Zygote.resetNicePriority();
- }
- ...
- //运行几个指定的GC,尝试清除几代的软引用和可达的对象,以及任何其他垃圾。
- //这只在fork()之前有用。强制进行了一次垃圾收集
- gcAndFinalize();
- ...
- //在fork之前调用一些安全初始化操作
- Zygote.nativeSecurityInit();
- //将整体的的存储目录/storage卸载,取而代之的是挂载临时目录,
- //这个动作和Android的沙箱(隔离存储)有关
- Zygote.nativeUnmountStorageOnInit();
- //呼应前面的ZygoteHooks.startZygoteNoThreadCreation()方法
- //告诉虚拟机,现在可以创建县城了
- ZygoteHooks.stopZygoteNoThreadCreation();
- if (startSystemServer) {//启动systemServer进程
- //这里的forkSystemServer方法导致进程进程发生了fork,也就是孵化裂变
- //从Zygote进程变成了Zygote和systemserver两个进程,fork会导致堆栈段的复制
- //进程会切换执行,涉及到CPU的切换,上下文的切换导致两个进程代码执行都停留在fork函数
- //两个进程都执行到fork函数等待返回,因此fork函数我们看代码是两次返回。
- //实际上fork函数的两次返回,是在两个进程中进行的:
- //先是在父进程中返回了被fork出来的子进程的pid
- //CPU执行切换到子进程之后因为在没有fork子进程,所以返回了0
- Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
- //如果r=null,说明当前代码在Zygote进程中执行,直接跳过
- if (r != null) {
- //如果r!=null,说明当前代码在子进程(systemserver)中执行
- //启动进程后返回
- //因为Runnable的run方法实际上包装了SystemServer的main方法,所以这里会运行main方法
- r.run();
- return;
- }
- }
- //走到这一步,代码没有返回,说明这里的代码是在Zygote进程中执行的,
- //因为如果是孵化的子进程的话,走不到这一步代码就return了
- //此处进入一个无限循环,处理Zygote Socket接收到的数据,
- caller = zygoteServer.runSelectLoop(abiList);
- } catch (Throwable ex) {
- Log.e(TAG, "System zygote died with exception", ex);
- throw ex;
- } finally {
- //关闭释放Sockte连接
- //这里的代码主要是给子进程调用的,因为Zygote进程在runSelectLoop中无限循环阻塞了,
- //正常情况不会执行到这
- //子进程是由Zygote这个父进程fork出来的,所以也会附带有Socket连接,
- //但是子进程不需要Zygote的Socket服务,这里保证关闭
- zygoteServer.closeServerSocket();
- }
- //我们在子进程中并退出了select循环。继续执行命令。
- if (caller != null) {
- caller.run();
- }
- }
- void registerServerSocketFromEnv(String socketName) {
- ...
- //这里的socketName来源于上面的main函数zygote
- //所以最终fullSocketName=ANDROID_SOCKET_zygote
- final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
- ...
- //找到名称为ANDROID_SOCKET_zygote的环境变量
- String env = System.getenv(fullSocketName);
- fileDesc = Integer.parseInt(env);
- ...
- FileDescriptor fd = new FileDescriptor();
- fd.setInt$(fileDesc);
- //创建一个本地socket服务,赋值给全局变量mServerSocket
- mServerSocket = new LocalServerSocket(fd);
- ...
- }
注意上面的这句代码:
String env = System.getenv(fullSocketName);
获取进程中名字为ANDROID_SOCKET_zygote的环境变量,那么这个环境变量是什么时候写进去的呢?我们前面分析/system/core/rootdir/init.rc(点击链接查看源码)时候讲到,他会解析/system/core/rootdir/init.zygote64.rc(点击链接查看源码)这个配置文件,init.zygote64.rc(点击链接查看源码)里面有这样一句socket zygote stream 660 root system,init进程在解析到这句配置的时候,会创建一个Socket fileDesc(简称socket fd)也就进程独有的文件描述符并且与ANDROID_SOCKET_zygote这个名字绑定,然后将socket名字(ANDROID_SOCKET_zygote)和socket fd注册到init进程的环境变量里面。其他进程都是init进程的子进程,可以通过System.getenv("ANDROID_SOCKET_zygote")获取到这个环境变量。
我们感兴趣的可以看下某 socket fd长什么样子?如下:
root@ubuntu:~# ll /proc/1583/fd
total 0
lrwx------ 1 root root 64 Jul 19 12:37 7 -> socket:[18892]
lrwx------ 1 root root 64 Jul 19 12:37 8 -> socket:[18893]
LocalSocket是Google为我们带来的,比Java的socket效率更高,没有经过协议栈,是Android自己实现的类似共享内存一样的东西,在传输大量数据的时候就需要用到。
Android的Java进程都是通过Zygote进程fork的,Zygote通过预加载类和资源可以加快子进程的执行速度和内存优化,因为预加载的类和资源比较多,所以开机时也需要重点关注preload的耗时。
- static void preload(TimingsTraceLog bootTimingsTraceLog) {
- //设置软引用保护,避免在预加载期间创建的引用被GC回收
- beginIcuCachePinning();
- //预加载系统类
- //读取设备本地/system/etc/preloaded-classes文件,解析该文件,
- //通过反射技术加载文件中声明的所有类,不同的手机厂商定义的类数量有差异,
- //有时需要加载数千个类,这也是设备启动慢的原因之一
- //Android12中preloaded-classes的源码在/frameworks/base/config/preloaded-classes
- preloadClasses();
- //预加载系统资源
- //com.android.internal.R.array.preloaded_drawables
- //com.android.internal.R.array.preloaded_color_state_lists
- //Android系统有一个framework-res.apk包,这些系统资源就是存在这个当中
- //Android应用可以使用这些公共资源
- preloadResources();
- //调用native方法加载HAL(硬件抽象层)代码
- //所谓HAL硬件抽象层
- nativePreloadAppProcessHALs();
- 加载OpenGL资源
- preloadOpenGL();
- //加载一些so库:libandroid.so、libcompiler_rt.so、libjnigraphics.so
- preloadSharedLibraries();
- //加载字体资源
- preloadTextResources();
- //要求WebViewFactory所有初始化必须在Zygote进程中进行
- WebViewFactory.prepareWebViewInZygote();
- //与前面的beginIcuCachePinning()呼应,取消软引用保护
- endIcuCachePinning();
- //初始化JCA相关参数
- warmUpJcaProviders();
-
- sPreloadComplete = true;
- }
Zygote进程启动时候预加载了不少资源,那么后续Zygote在fork新进程的时候,采用了COW(copy-on-write)技术,即写时拷贝技术。当App通过fork创建的时候,为了节省开销、加快应用启动,Zygote fork子进程不进行内存复制,而是共享Zygote进程预加载的系统类和系统资源,只有当子进程需要修改共享资源时,才会将共享内存复制到自己的进程内做修改。
SystemServer是Android基本服务的提供者,是Android系统运行的最基本需求,所有Service运行在一个叫system_server的进程中,system_server为Android系统提供了各种Service。system_server进程是Android Java虚拟机中第一个进程,可以说整个Android系统的业务都是system_server展开的。
forkSystemServer方法,为孵化SystemServer进程准备参数,并且fork出systemServer进程
注意,forkSystemServer方法因为是fork新的进程出来,新进程代码也会执行到forkSystemServer方法,这就会导致Zygote进程、system_server进程一起从fork函数返回。如果方法是在Zygote进程中执行的,则返回被fork出的SystemServer进程的Runnable对象;如果方法是在SystemServer进程中执行的,则因为其没有继续fork子进程,所以没有需要执行的Runnable任务,返回null
- private static Runnable forkSystemServer(String abiList, String socketName,
- ZygoteServer zygoteServer) {
- ...
- //参数准备
- String args[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
- "--capabilities=" + capabilities + "," + capabilities,
- "--nice-name=system_server",
- "--runtime-args",
- "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
- "com.android.server.SystemServer",
- };
- ZygoteConnection.Arguments parsedArgs = null;
-
- int pid;
-
- try {
- //参数解析,生成目标函数
- parsedArgs = new ZygoteConnection.Arguments(args);
- ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
- ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
-
- boolean profileSystemServer = SystemProperties.getBoolean(
- "dalvik.vm.profilesystemserver", false);
- if (profileSystemServer) {
- parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
- }
- //这里是重点,fork出system_server进程,并运行system_server进程
- //fork动作会产生一个新的与Zygote一样的新的进程,并且云心新进程,
- //这样就导致了Zygote进程与system_server两个进程CPU执行权切换,
- //两个进程都停留在fork方法等待返回,两个fork方法是在两个进程中运行的,自然分别有对应返回值。
- //当fork方法运行在Zygote进程中时候,则返回其fork出子进程的pid,也就是system_server的pid;
- //当fork方法运行在system_server进程中时候,因为其没有继续fork的子进程,所以返回0
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids,
- parsedArgs.runtimeFlags,
- null,
- parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IllegalArgumentException ex) {
- throw new RuntimeException(ex);
- }
-
- /* For child process */
- if (pid == 0) {
- //走到这里说明当前代码运行在system_Server进程当中
- if (hasSecondZygote(abiList)) {
- //如果设备同时配置了两个Zygote进程,那么这里等待第二个Zygote进程
- //这里主要是一些设备配置了init.zygote32_64.rc或者init.zygote64_32.rc
- //这样就会启动两个Zygote进程,一个为主,一个为次
- waitForSecondaryZygote(socketName);
- }
- //子进程是由Zygote孵化出来的,所以也具备了zygoteServer的Socket服务
- //但是子进程用不到,所以直接关闭
- zygoteServer.closeServerSocket();
- //handleSystemServerProcess方法的作用:
- //利用反射技术找到SystemServer的main函数,并将这个函数包装到Runnable的run方法中
- //返回包装后的Runnable对象
- return handleSystemServerProcess(parsedArgs);
- }
- return null;
- }
Zygote进程会启动一个Socket本地服务,等待Socket客户端连接请求,当新的App启动的时候,就会请求zygote server服务fork新的进程。
zygoteServer.runSelectLoop会进入循环阻塞等待,等待处理启动新应用的请求,一旦收到请求会fork新的进程出来。
与上面的forkSystemServer一个道理,Zygote在fork新的进程,就会造成新老进程的runSelectLoop方法都执行但是返回值不同。当在子进程中时,会跳出runSelectLoop的循环,返回Runnable对象,也就是说在子进程中是不存在阻塞的,Zygote进程会保持阻塞监控新的连接请求
- Runnable runSelectLoop(String abiList) {
- ArrayList
fds = new ArrayList(); - ArrayList
peers = new ArrayList(); - //执行完下面这句代码,表示fds中只有一个元素,那就是mServerSocket
- fds.add(mServerSocket.getFileDescriptor());
- peers.add(null);
- while (true) {
- //每次循环都会动态创建新的pollFds
- StructPollfd[] pollFds = new StructPollfd[fds.size()];
- for (int i = 0; i < pollFds.length; ++i) {
- pollFds[i] = new StructPollfd();
- pollFds[i].fd = fds.get(i);
- //关注事件的到来
- pollFds[i].events = (short) POLLIN;
- }
- try {
- //Os.pull是Linux系统的一个处理文件描述符的方法,等待文件描述符上的某个事件,I/O服用机制
- //监听pollFds数组中的事件,当pollFds有事件到来就往下执行
- //这里的-1表示当没有事件到来时一直阻塞,
- Os.poll(pollFds, -1);
- } catch (ErrnoException ex) {
- throw new RuntimeException("poll failed", ex);
- }
- //代码走到这里说明上面的poll阻塞方法有返回了,也就是pollFds有数据到来了
- for (int i = pollFds.length - 1; i >= 0; --i) {
- if ((pollFds[i].revents & POLLIN) == 0) {
- //采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
- //否则进入continue,跳出本次循环。
- continue;
- }
- if (i == 0) {
- //fds[0]是mServerSocket
- //Socket服务端是LocalServerSocket,Socket客户端应该是LocalSocket
- //acceptCommandPeer方法就是给mServerSocket创建了一个与之连接的LocalSocket客户端
- //ZygoteConnection内部分装了LocalSocket客户端
- ZygoteConnection newPeer = acceptCommandPeer(abiList);
- peers.add(newPeer);
- //将通信对象添加到fds
- fds.add(newPeer.getFileDesciptor());
- } else {
- //这里就是遍历到了上面新添加的Socket通信对象
- try {
- ZygoteConnection connection = peers.get(i);
- //processOneCommand会读取参数并且fork新的子进程及相关操作
- //因为这里最终会是fork操作,所以同样的会造成父进程子进程都运行这段代码
- //当在子进程中运行,则command不为空,Zygote中command为空
- final Runnable command = connection.processOneCommand(this);
- if (mIsForkChild) {
- //已经fork了子进程,并且当前代码运行在子进程
- if (command == null) {
- //保证fork子进程后必须有command返回
- throw new IllegalStateException("command == null");
- }
- //在子进程中,返回command
- return command;
- } else {
- if (command != null) {
- //保证父进程不能存在command
- throw new IllegalStateException("command != null");
- }
- //Zygote进程,完成了子进程的fork后,应该关闭本次的Socket连接,并清除该连接
- if (connection.isClosedByPeer()) {
- connection.closeSocket();
- peers.remove(i);
- fds.remove(i);
- }
- }
- } catch (Exception e) {
- if (!mIsForkChild) {
- //发生异常后清除操作
- ZygoteConnection conn = peers.remove(i);
- conn.closeSocket();
-
- fds.remove(i);
- } else {
- Log.e(TAG, "Caught post-fork exception in child process.", e);
- throw e;
- }
- } finally {
- //每次处理完客户端请求后,保证mIsForkChild为false
- mIsForkChild = false;
- }
- }
- }
- }
- }
下面看下connection.processOneCommand(this)方法的源码
- Runnable processOneCommand(ZygoteServer zygoteServer) {
- String args[];
- Arguments parsedArgs = null;
- FileDescriptor[] descriptors;
- try {
- //读取参数
- args = readArgumentList();
- descriptors = mSocket.getAncillaryFileDescriptors();
- } catch (IOException ex) {
- throw new IllegalStateException("IOException on command socket", ex);
- }
- ...
- //解析参数
- parsedArgs = new Arguments(args);
- if (parsedArgs.abiListQuery) {
- handleAbiListQuery();
- return null;
- }
- if (parsedArgs.preloadDefault) {
- handlePreload();
- return null;
- }
- if (parsedArgs.preloadPackage != null) {
- handlePreloadPackage(parsedArgs.preloadPackage, parsedArgs.preloadPackageLibs,
- parsedArgs.preloadPackageLibFileName, parsedArgs.preloadPackageCacheKey);
- return null;
- }
- if (parsedArgs.apiBlacklistExemptions != null) {
- handleApiBlacklistExemptions(parsedArgs.apiBlacklistExemptions);
- return null;
- }
- if (parsedArgs.hiddenApiAccessLogSampleRate != -1) {
- handleHiddenApiAccessLogSampleRate(parsedArgs.hiddenApiAccessLogSampleRate);
- return null;
- }
- if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
- throw new ZygoteSecurityException("Client may not specify capabilities: " +
- "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
- ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
- }
- //参数检查和设置
- // 检查客户端手有权限指定进程的用户ID、组ID
- // 如果是 root 进程,可以任意指定
- // 如果是 sys 进程,需要在ro.factorytest值 > 0时可以指定
- applyUidSecurityPolicy(parsedArgs, peer);
- // 判断是否具有invoke-with的执行权限
- applyInvokeWithSecurityPolicy(parsedArgs, peer);
- // 如果ro.debuggable是1的话,启动JDWP协议
- applyDebuggerSystemProperty(parsedArgs);
- // 如果ro.debuggable是1的话,启动JDWP协议
- applyInvokeWithSystemProperty(parsedArgs);
- ...
- //fork子进程,fork方法孵化子进程后,与Zygote进程都会运行并返回值
- //当前代码运行在Zygote进程中时,返回的pid就是fork得到的子进程的pid
- //当前代码如果运行在子进程中,则pid=0
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
- parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
- parsedArgs.instructionSet, parsedArgs.appDataDir);
- try {
- if (pid == 0) {
- //当前处于子进程中
- zygoteServer.setForkChild();
- //子进程由Zygote进程fork出来,所以也具备了zygoteServer,但是不需要,所以关闭
- zygoteServer.closeServerSocket();
- IoUtils.closeQuietly(serverPipeFd);
- serverPipeFd = null;
- //在子进程中完成子进程的初始化工作
- return handleChildProc(parsedArgs, descriptors, childPipeFd,
- parsedArgs.startChildZygote);
- } else {
- //fork完子进程后,父进程中处理一些关闭及清理的工作
- IoUtils.closeQuietly(childPipeFd);
- childPipeFd = null;
- handleParentProc(pid, descriptors, serverPipeFd);
- return null;
- }
- } finally {
- IoUtils.closeQuietly(childPipeFd);
- IoUtils.closeQuietly(serverPipeFd);
- }
- }
我们来看下fork出子进程之后,子进程是如何完成初始化的操作的,handleChildProc方法源码如下
- private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
- FileDescriptor pipeFd, boolean isZygote) {
- //关闭本次操作的Socket连接
- closeSocket();
- ...
- if (parsedArgs.invokeWith != null) {
- //启动参数有--invoke-with
- WrapperInit.execApplication(parsedArgs.invokeWith,
- parsedArgs.niceName, parsedArgs.targetSdkVersion,
- VMRuntime.getCurrentInstructionSet(),
- pipeFd, parsedArgs.remainingArgs);
-
- // Should not get here.
- throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
- } else {//通常情况下--invoke-with参数为空,所以代码会进入这里
- if (!isZygote) {
- //很显然当前是在子进程运行而非Zygote进程中,所以代码执行这里
- return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
- null /* classLoader */);
- } else {
- return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
- parsedArgs.remainingArgs, null /* classLoader */);
- }
- }
- }
我们进入ZygoteInit.zygoteInit方法
- public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
- String[] argv, ClassLoader classLoader) {
- ...
- //一些通用的简单初始化
- RuntimeInit.commonInit();
- //调用了一个本地native方法,最终调用了我们前面提到的AndroidRuntime的子类AppRuntime的onZygoteInit()方法
- //初始化binder的使用环境
- ZygoteInit.nativeZygoteInit();
- //这里最终调用了RuntimeInit.findStaticMain方法
- return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
- classLoader);
- }
我们先来看一下AppRuntime的onZygoteInit()方法的源码,源码在app_main.cpp的AppRuntime下面
- virtual void onZygoteInit(){
- sp
proc = ProcessState::self(); - ALOGV("App process: starting thread pool.\n");
- proc->startThreadPool();
- }
这个onZygoteInit主要就是用来初始化Binder的使用环境
我们最后看下RuntimeInit.findStaticMain方法,其实这个方法在前面forkSystemServer中也用过这个方法,findStaticMain方法,会将参数传入的className通过反射的技术,找到其main方法,并且包装到Runnable的run方法中返回
- protected static Runnable findStaticMain(String className, String[] argv,
- ClassLoader classLoader) {
- Class> cl;
-
- try {
- cl = Class.forName(className, true, classLoader);
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- "Missing class when invoking static main " + className,
- ex);
- }
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- } catch (NoSuchMethodException ex) {
- throw new RuntimeException(
- "Missing static main on " + className, ex);
- } catch (SecurityException ex) {
- throw new RuntimeException(
- "Problem getting static main on " + className, ex);
- }
- ...
- return new MethodAndArgsCaller(m, argv);
- }
- static class MethodAndArgsCaller implements Runnable {
- private final Method mMethod;
- private final String[] mArgs;
- public MethodAndArgsCaller(Method method, String[] args) {
- mMethod = method;
- mArgs = args;
- }
- public void run() {
- ...
- mMethod.invoke(null, new Object[] { mArgs });
- ...
- }
- }
而我们这里,handleChildProc方法,最终返回的MethodAndArgsCaller(Runnable的子类),实际上是利用反射技术将android.app.ActivityThread的main()方法封装到Runnable的run()方法里面。而ActivityThread的main方法正式整个App入口。
我们回顾一下ZygoteInit.main方法的最后处理逻辑
- public static void main(String argv[]) {
- ...
- final Runnable caller;
- try {
- ...
- if (startSystemServer) {//启动systemServer进程
- Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
- if (r != null) {
- r.run();
- return;
- }
- }
- //如果当前代码运行在Zygote进程,则返回null
- //如果当前代码运行在子进程,则返回caller
- caller = zygoteServer.runSelectLoop(abiList);
- } catch (Throwable ex) {
- Log.e(TAG, "System zygote died with exception", ex);
- throw ex;
- } finally {
- zygoteServer.closeServerSocket();
- }
- //根据前面的讲解,我们能够知道Zygote在fork进程时会发生两个进程各自运行同一处代码,
- //根据桑上面的runSelectLoop方法会将Zygote进程处于阻塞状态,无限循环等待Socket客户端
- //发起请求,比如App的启动会出发zygoteServer与Zocket客户端连接,然后fork出App的进程
- //当代码运行在App进程(子进程)中时,将会跳出阻塞,返回caller,Zygote父进程继续保持
- //阻塞监听。
- if (caller != null) {
- //执行到这一步,我们可以确定当前代码运行在子进程,此处的run方法运行的就是ActivityThread
- //的main方法。
- caller.run();
- }
- }
Android启动一个新的进程都是在ActivityManagerService(简称AMS)中完成的,可能会有很多原因导致系统启动一个新的进程,最终在AMS中都是通过调用startProcess()方法来实现。
通过查看ActivityManagerService.startProcess的源码,找到了关键的代码,最终调用了ZygoteProcess类的一个私有方法startViaZygote()方法,我们重点看下startViaZygote的关键代码
- private Process.ProcessStartResult startViaZygote(final String processClass,
- final String niceName,
- final int uid, final int gid,
- final int[] gids,
- int runtimeFlags, int mountExternal,
- int targetSdkVersion,
- String seInfo,
- String abi,
- String instructionSet,
- String appDataDir,
- String invokeWith,
- boolean startChildZygote,
- String[] extraArgs)
- throws ZygoteStartFailedEx {
- ArrayList
argsForZygote = new ArrayList(); - // --runtime-args, --setuid=, --setgid=,
- // and --setgroups= must go first
- argsForZygote.add("--runtime-args");
- argsForZygote.add("--setuid=" + uid);
- argsForZygote.add("--setgid=" + gid);
- argsForZygote.add("--runtime-flags=" + runtimeFlags);
- if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
- argsForZygote.add("--mount-external-default");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
- argsForZygote.add("--mount-external-read");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
- argsForZygote.add("--mount-external-write");
- }
- argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
- // --setgroups is a comma-separated list
- if (gids != null && gids.length > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append("--setgroups=");
- int sz = gids.length;
- for (int i = 0; i < sz; i++) {
- if (i != 0) {
- sb.append(',');
- }
- sb.append(gids[i]);
- }
- argsForZygote.add(sb.toString());
- }
- if (niceName != null) {
- argsForZygote.add("--nice-name=" + niceName);
- }
- if (seInfo != null) {
- argsForZygote.add("--seinfo=" + seInfo);
- }
- if (instructionSet != null) {
- argsForZygote.add("--instruction-set=" + instructionSet);
- }
- if (appDataDir != null) {
- argsForZygote.add("--app-data-dir=" + appDataDir);
- }
- if (invokeWith != null) {
- argsForZygote.add("--invoke-with");
- argsForZygote.add(invokeWith);
- }
- if (startChildZygote) {
- argsForZygote.add("--start-child-zygote");
- }
- argsForZygote.add(processClass);
- if (extraArgs != null) {
- for (String arg : extraArgs) {
- argsForZygote.add(arg);
- }
- }
- //关键代码就是这一句
- //1,openZygoteSocketIfNeeded会创建与Zygote进程ServerSocket的连接
- //2,zygoteSendArgsAndGetResult会将进程启动的参数发送给Zygote进程,fork出新进程后会将进程的pid返回
- synchronized(mLock) {
- return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
- }
- }
openZygoteSocketIfNeeded方法源码
- private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
- Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
-
- if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
- try {
- //与Zygote的Socket服务建立连接
- primaryZygoteState = ZygoteState.connect(mSocket);
- } catch (IOException ioe) {
- throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
- }
- ...
- }
- ...
- if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
- try {
- //针对一些设备配置了init.zygote32_64.rc或者init.zygote64_32.rc
- //需要与另一个Zygote的Socket服务建立连接
- secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
- } catch (IOException ioe) {
- throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
- }
- ...
- }
- ...
- }
ZygoteState的connect方法
- public static ZygoteState connect(LocalSocketAddress address) throws IOException {
- ...
- final LocalSocket zygoteSocket = new LocalSocket();
- ...
- try {
- zygoteSocket.connect(address);
- ...
- } catch (IOException ex) {
- try {
- zygoteSocket.close();
- } catch (IOException ignore) {
- }
- throw ex;
- }
- ...
- return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
- Arrays.asList(abiListString.split(",")));
- }
zygoteSendArgsAndGetResult方法源码
- private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
- ZygoteState zygoteState, ArrayList
args) - throws ZygoteStartFailedEx {
- ...
- //输出流,参数写入给Zygote
- final BufferedWriter writer = zygoteState.writer;
- //输入流,从Zygote进程读取fork得到的新进程
- final DataInputStream inputStream = zygoteState.inputStream;
-
- writer.write(Integer.toString(args.size()));
- writer.newLine();
- for (int i = 0; i < sz; i++) {
- String arg = args.get(i);
- writer.write(arg);
- writer.newLine();
- }
- //App启动参数写入发送
- writer.flush();
-
- //fork子进程后读取新的进程
- Process.ProcessStartResult result = new Process.ProcessStartResult();
- result.pid = inputStream.readInt();
- result.usingWrapper = inputStream.readBoolean();
- ...
- return result;
- } catch (IOException ex) {
- zygoteState.close();
- throw new ZygoteStartFailedEx(ex);
- }
- }
Android系统启动流程,前两步我们简单说明下
1,BootLoader
BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境;
2,Kernel
Kernel指的是操作系统内核Linux初始化及启动;
3,init进程启动
硬件初始化、内核初始化及启动之后,init将会启动
init进程启动先调用了init.cpp中的main()方法,init.cpp的main()方法中有这样一句代码:parser.ParseConfig("/init.rc"),解析init.rc文件,init.rc文件中有zygote start等启动zygote的命令,而且有导入zygote配置的语句import /system/etc/init/hw/init.${ro.zygote}.rc,$(ro.zygote).rc这个引用具体会指向设备具体的配置文件,配置文件按照不同的硬件厂商目前有3种:
init.zygote32.rc、init.zygote32_64.rc、init.zygote64.rc,这三种文件决定了启动32位还是64位的Zygote服务。不过这几个文件中第一行配置就是service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server这一句,service zygote意思是Zygote进程是以Service服务的方式启动,所以会先启动一个Zygote service服务,/system/bin/app_process64表示回去执行app_process,最终会去执行app_main.cpp中的main方法,并且会将下面的参数传给app_main.cpp的main方法:
app_main.cpp的main方法,主要干了三件事:
AndroidRuntime的start方法主要做三件事
我们上面的分析,传给start方法的className是ZygoteInit,所以最终会调用ZygoteInit的main方法
我的理解是Zygote进程在上面的init解析init.zygote.rc配置文件后,以service的方式启动了。所以在调用ZygoteInit.java的main方法之前,Zygote进程已经启动了
ZygoteInit的main方法是通过Zygote进程去调用的,总结一下ZygoteInit.java的main方法做了什么:
(133条消息) android中AMS通知Zygote去fork进程为什么使用socket而不使用binder?_失落夏天的博客-CSDN博客_安卓socke zygote