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

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就说明是运行在子进程中

这个还是很有意思的,关于Linux的fork系统调用,后面关于Linux知识时,再细说一下。

runSelectLoop

这个的设计也非常巧妙,runSelectLoop的作用就是从前面创建的Socket服务端中循环取出其他进程发来的消息,当消息结果caller不为空时,执行这个消息

这里就要想个问题,因为是多进程,执行该方法也可能是其他进程,比如前面刚刚创建的systemServer进程,但是我们还记得创建的systemServer进程已经关闭socket了,所以这里的选择循环会一直运行在Zygote进程中

该方法代码如下:

/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
144 ArrayList fds = new ArrayList();
145 ArrayList peers = new ArrayList();
146 //这个mServerSocket就是前面创建的服务端Socket
147 fds.add(mServerSocket.getFileDescriptor());
148 peers.add(null);
149 //无限循环等待AMS请求Zygote进程创建新的应用进程。
150 while (true) {
151 StructPollfd[] pollFds = new StructPollfd[fds.size()];
152 for (int i = 0; i < pollFds.length; ++i) {
153 pollFds[i] = new StructPollfd();
154 pollFds[i].fd = fds.get(i);
155 pollFds[i].events = (short) POLLIN;
156 }
157 try {
158 Os.poll(pollFds, -1);
159 } catch (ErrnoException ex) {
160 throw new RuntimeException(“poll failed”, ex);
161 }
162 for (int i = pollFds.length - 1; i >= 0; --i) {
163 if ((pollFds[i].revents & POLLIN) == 0) {
164 continue;
165 }
166 //i等于0,说明服务端Socket和客户端连接上了,即Zygote进程和AMS建立了链接
167 if (i == 0) {
168 ZygoteConnection newPeer = acceptCommandPeer(abiList);
169 peers.add(newPeer);
170 fds.add(newPeer.getFileDesciptor());
171 } else {
172 try {
173 ZygoteConnection connection = peers.get(i);
//会创建子进程
174 final Runnable command = connection.processOneCommand(this);
176 if (mIsForkChild) {
179 if (command == null) {
180 throw new IllegalStateException(“command == null”);
181 }
183 return command;
184 } else {
186 if (command != null) {
187 throw new IllegalStateException(“command != null”);
188 }
193 if (connection.isClosedByPeer()) {
194 connection.closeSocket();
195 peers.remove(i);
196 fds.remove(i);
197 }
198 }
199 } catch (Exception e) {
200 …
222 }
223 }
224 }
225 }
226 }

这里说明了一种进程通信方式,即Zygote进程和AMS所在的进程(systemServer进程)的通信方式是Socket,关于这部分细节内容,等后面创建应用进程时再细说。

在Java层的Zygote进程流程分析中,涉及了如下几个Java类,这里简单总结一下:

总结

Zygote进程作为开启Java世界大门的重要进程,简单总结一下其启动流程和作用:

  • 在Native层:
    1.创建Java虚拟机,这也是Android系统能运行Java代码的底层原因。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
img

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

真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
[外链图片转存中…(img-nl1521Xv-1712656579476)]

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

  • 28
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值