Framework原理分析之——Zygote进程流程分析_android zygote fork进程流程(1)

1081 }
1082
1083 //有了JNI,我们这里就可以调用Java方法了
1088 jclass stringClass;
1089 jobjectArray strArray;
1090 jstring classNameStr;
1091 //由传进来的参数可以知道,Java世界的Zygote初始化类是
//“com.android.internal.os.ZygoteInit”
1092 stringClass = env->FindClass(“java/lang/String”);
1093 assert(stringClass != NULL);
1094 strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
1095 assert(strArray != NULL);
1096 classNameStr = env->NewStringUTF(className);
1097 assert(classNameStr != NULL);
1098 env->SetObjectArrayElement(strArray, 0, classNameStr);
1099
1100 for (size_t i = 0; i < options.size(); ++i) {
1101 jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1102 assert(optionsStr != NULL);
1103 env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1104 }
1105
1106 //将className的".“替换为”/"
1110 char* slashClassName = toSlashClassName(className != NULL ? className : “”);
1111 jclass startClass = env->FindClass(slashClassName);
1112 if (startClass == NULL) {
1113 ALOGE(“JavaVM unable to locate class ‘%s’\n”, slashClassName);
1114 /* keep going /
1115 } else {
//找到了ZygoteInit的main方法
1116 jmethodID startMeth = env->GetStaticMethodID(startClass, “main”,
1117 “([Ljava/lang/String;)V”);
1118 if (startMeth == NULL) {
1119 ALOGE(“JavaVM unable to find main() in ‘%s’\n”, className);
1120 /
keep going */
1121 } else {
//调用main方法,开启愉快的Java之旅
1122 env->CallStaticVoidMethod(startClass, startMeth, strArray);
1123
1124#if 0
1125 if (env->ExceptionCheck())
1126 threadExitUncaughtException(env);
1127#endif
1128 }
1129 }
1130 free(slashClassName);
1137}


这个类就是我们之前在说架构时的AndroidRuntime部分代码,它其实是C++代码,在文中都注释了非常明白了,主要做了如下事:


1. **启动Java虚拟机**,想运行Java代码,必须要创建Java虚拟机程序,在这里会创建和启动java虚拟机。关于虚拟机的知识,后面文章会单独分析。
2. **注册JNI方法**,关于JNI的原理后面会细说,说白了就是Java可以调用C/C++程序,而C/C++程序可以调用Java代码,也就是通过JNI打通了Java世界和Native世界的屏障。这里注册JNI方法,其实就是为了后面使用JNI而做准备。  
 3.根据传入的Java类名,通过JNI找到Java类,然后把".“换成”/“,这是因为在JNI中是不允许以”."作为变量名的,后面细说;然后再通过JNI方法,调用该类的main函数。


由于ZygoteInit的main方法由Java编写,这样Zygote就从Native层进入了Java框架层。


### Java层流程分析


还是先来看一下大致调用流程图:


![](https://img-blog.csdnimg.cn/img_convert/2ecdf3a4a1e8650cf713c5fd3749dabe.png)


`话不多说,我们来看看Java世界的该方法:



/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
//新建ZygoteServer实例
699 ZygoteServer zygoteServer = new ZygoteServer();
700
701 …
747 //创建一个Server端的Socket,socketName就是"zygote"
748 zygoteServer.registerServerSocket(socketName);
749
751 if (!enableLazyPreload) {
752 bootTimingsTraceLog.traceBegin(“ZygotePreload”);
753 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
754 SystemClock.uptimeMillis());
//预加载资源
755 preload(bootTimingsTraceLog);
756 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
757 SystemClock.uptimeMillis());
758 bootTimingsTraceLog.traceEnd(); // ZygotePreload
759 } else {
760 Zygote.resetNicePriority();
761 }
762
763 …
780
781 if (startSystemServer) {
//创建和启动SystemServer进程
782 Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
786 if (r != null) {
787 r.run();
788 return;
789 }
790 }
791
792 //等待AMS请求
796 caller = zygoteServer.runSelectLoop(abiList);
797 } catch (Throwable ex) {
798 Log.e(TAG, “System zygote died with exception”, ex);
799 throw ex;
800 } finally {
//一直循环,这个只有Zygote进程死了才会执行
801 zygoteServer.closeServerSocket();
802 }
806 if (caller != null) {
807 caller.run();
808 }
809 }


这里简化了很多逻辑,我们只分析一些主要的流程,从上面注释我们可以知道,ZygoteInit的main函数主要做了如下几件事:


1.**创建了一个Server端的Socket**,该Socket的主要作用就一个,就是等待ActivityManagerService(AMS)的请求,**来创建新的进程**。关于AMS我们肯定听过,它负责Android四大组件的运行,而其中就有一个场景就是启动新的APP进程,这时就需要创建新进程,而创建新进程的工作就是这里。  
 2.**加载类和资源。**  
 3.**孵化和启动SystemServer进程**,该进程比较重要,我们熟悉的AMS、WMS等系统服务都是运行在该进程中,后面分析SystemServer进程时,我们再仔细分析。


上面就是Zygote进程在Java层所做的主要工作,我们来简单梳理一下。


#### 创建本地Server Socket


主要是通过调用ZygoteServer中的registerServerSocket方法:



/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
//新建ZygoteServer实例
699 ZygoteServer zygoteServer = new ZygoteServer();
700
701 …
747 //创建一个Server端的Socket,socketName就是"zygote"
748 zygoteServer.registerServerSocket(socketName);
749
751 if (!enableLazyPreload) {
752 bootTimingsTraceLog.traceBegin(“ZygotePreload”);
753 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
754 SystemClock.uptimeMillis());
//预加载资源
755 preload(bootTimingsTraceLog);
756 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
757 SystemClock.uptimeMillis());
758 bootTimingsTraceLog.traceEnd(); // ZygotePreload
759 } else {
760 Zygote.resetNicePriority();
761 }
762
763 …
780
781 if (startSystemServer) {
//创建和启动SystemServer进程
782 Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
786 if (r != null) {
787 r.run();
788 return;
789 }
790 }
791
792 //等待AMS请求
796 caller = zygoteServer.runSelectLoop(abiList);
797 } catch (Throwable ex) {
798 Log.e(TAG, “System zygote died with exception”, ex);
799 throw ex;
800 } finally {
//一直循环,这个只有Zygote进程死了才会执行
801 zygoteServer.closeServerSocket();
802 }
806 if (caller != null) {
807 caller.run();
808 }
809 }


这里注意创建本地Socket的代码是在ZygoteServer.java中,这个mServerSocket在后面会被使用,等会再说。


### 预加载资源


在Zygote进程的初始化过程中,会预加载一些必要的资源,方法如下:



/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
static void preload(TimingsTraceLog bootTimingsTraceLog) {
123 //预加载类,这里使用类加载器加载/system/ect/preload-class下定义的类
//该文件是一个文本文件,以全包名的方式写了几百个类
128 preloadClasses();
129 //预加载资源,主要是加载一些图片、颜色等资源到内存中
131 preloadResources();
132 //预加载OpenGL
137 preloadOpenGL();
138 //通过System.loadLibrary方式加载3个共享库
//分别是android、compiler_rt、jnigraphics
139 preloadSharedLibraries();
//加载文本等资源
140 preloadTextResources();
141 …
149 }


这里加载资源非常关键,由前面我们知道到目前**Zygote进程已经有虚拟机实例、预加载了部分资源和Java类,以及预加载了共享库**,这时创建子进程时,是通过fork形式的,即**复制自己,新的进程也会有这些内容**。


关于这部分加载类的细节,涉及类加载器、Class类等知识,后面文章会详细分析。


#### 启动SystemServer进程


Zygote进程的另一个重要工作就是启动SystemServer进程,我们来看看Java世界中是如何启动进程的:



/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
621 ZygoteServer zygoteServer) {
622 long capabilities = posixCapabilitiesAsBits(
623 OsConstants.CAP_IPC_LOCK,
624 OsConstants.CAP_KILL,
625 OsConstants.CAP_NET_ADMIN,
626 OsConstants.CAP_NET_BIND_SERVICE,
627 OsConstants.CAP_NET_BROADCAST,
628 OsConstants.CAP_NET_RAW,
629 OsConstants.CAP_SYS_MODULE,
630 OsConstants.CAP_SYS_NICE,
631 OsConstants.CAP_SYS_PTRACE,
632 OsConstants.CAP_SYS_TIME,
633 OsConstants.CAP_SYS_TTY_CONFIG,
634 OsConstants.CAP_WAKE_ALARM
635 );

637 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
638 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
639 }
640 //设置参数
641 String args[] = {
642 “–setuid=1000”,
643 “–setgid=1000”,
644 “–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010”,
645 “–capabilities=” + capabilities + “,” + capabilities,
646 “–nice-name=system_server”,
647 “–runtime-args”,
648 “com.android.server.SystemServer”,
649 };
650 ZygoteConnection.Arguments parsedArgs = null;
651
652 int pid;
653
654 try {
//这里是为了把硬编码的参数转换成特定类对象
655 parsedArgs = new ZygoteConnection.Arguments(args);
656 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
657 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
658
659 //fork新进程
660 pid = Zygote.forkSystemServer(
661 parsedArgs.uid, parsedArgs.gid,
662 parsedArgs.gids,
663 parsedArgs.debugFlags,
664 null,
665 parsedArgs.permittedCapabilities,
666 parsedArgs.effectiveCapabilities);
667 } catch (IllegalArgumentException ex) {
668 throw new RuntimeException(ex);
669 }
670
671 //pid为0,说明当前是子进程
672 if (pid == 0) {
673 if (hasSecondZygote(abiList)) {
674 waitForSecondaryZygote(socketName);
675 }
676 //子进程即SystemServer进程不需要监听socket
677 zygoteServer.closeServerSocket();
//SystemServer进程处理它的事务
678 return handleSystemServerProcess(parsedArgs);
679 }
680
681 return null;
682 }


该部分是创建、启动SystemServer进程,首先是用代码来创建args数组,也就是启动参数,从参数我们可以看出SystemServer进程的用户id和用户组id被设置为1000,并且拥有1001-1010、1018、1021、1032、3001-3010用户组的权限;**进程名为system\_server,启动的类名为com.android.server.SystemServer**。


然后通过Zygote类的**forkSystemServer函数创建了一个子进程**,该方法底层调用了native方法,原理也就是Linux的fork系统调用。然后有个非常有意思的地方,就是pid为0表示是子进程,这里或许有点疑惑,这里是为什么?


这时就要从多进程和fork的含义来理解了,fork的意思是复制,即调用完fork后,**新的systemServer进程会有和Zygote进程一样的信息,比如虚拟机、预加载的资源等,那这时就相当于2个进程都运行到这里了,那如何分道扬镳呢 就看这个pid的值,如果是0就说明是运行在子进程中**。



## 总结

笔者之前工作是在金融公司可能并不是特别追求技术,而笔者又是喜欢追求技术的人,所以格格不入,只能把目标放在互联网大厂了。也希望大家都去敢于尝试和追逐自己的梦想!
**BATJ大厂Android高频面试题**

![](https://img-blog.csdnimg.cn/img_convert/b6c165fdf8c1787034a8b37ec7d2c729.webp?x-oss-process=image/format,png) 

![](https://img-blog.csdnimg.cn/img_convert/9d07562518445f9e89fe876d56ea3fb8.webp?x-oss-process=image/format,png) 

![](https://img-blog.csdnimg.cn/img_convert/ceeba526a08293bdae11b6bbb8b9efa9.webp?x-oss-process=image/format,png) 

![](https://img-blog.csdnimg.cn/img_convert/aafc81a9bab29a2ac9df36f54d7159b4.webp?x-oss-process=image/format,png) 

**觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!** 



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

4453)] 

[外链图片转存中...(img-ucBqtDzR-1714496884454)] 

**觉得有收获的记得点赞,关注+收藏哦!你们的点赞就是我的动力!** 



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值