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

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

Java层流程分析

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

`话不多说,我们来看看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就说明是运行在子进程中

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

runSelectLoop

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

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

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

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

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

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

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

真正体系化!**

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值