2024面试,深入研究源码,开发这么久这些问题都不会

}

这篇文章的目的是分析zygote的流程,那我们暂时只关心zygote相关的逻辑

函数最后调用了ZygoteInit,我们看看这个类主要做了什么

/framework/base/core/java/com/android/internal/os/ZygoteInit.java

按照之前的套路,我们先找到入口函数main

@UnsupportedAppUsage
public static void main(String argv[]) {
// Server socket class for zygote processes.
ZygoteServer zygoteServer = null; //用来管理和子进程通信的socket服务端

// Mark zygote start. This ensures that thread creation will throw
// an error.

ZygoteHooks.startZygoteNoThreadCreation(); //这里其实只是设置一个标志位,为创建Java线程时做判断处理,如果是zygote进程,则不需要开启线程

// Zygote goes into its own process group.
try {
Os.setpgid(0, 0); //为zygote进程设置pgid(Process Group ID),详见:https://stackoverflow.com/questions/41498383/what-do-the-identifiers-pid-ppid-sid-pgid-uid-euid-mean
} catch (ErrnoException ex) {
throw new RuntimeException(“Failed to setpgid(0,0)”, ex);
}

Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!“1”.equals(SystemProperties.get(“sys.boot_completed”))) { //获取系统属性,判断系统重启完成
MetricsLogger.histogram(null, “boot_zygote_init”,
(int) SystemClock.elapsedRealtime());
}

String bootTimeTag = Process.is64Bit() ? “Zygote64Timing” : “Zygote32Timing”;//判断当前进程是64位程序还是32位程序,并设置标记
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin(“ZygoteInit”);
RuntimeInit.enableDdms();//注册到ddms服务端,内部调用DdmServer.registerHandler()

boolean startSystemServer = false;
String zygoteSocketName = “zygote”;
String abiList = null;
boolean enableLazyPreload = false;
//对参数进行解析
for (int i = 1; i < argv.length; i++) {
if (“start-system-server”.equals(argv[i])) { //参数重包含start-system-server
startSystemServer = true; //设置标志为位true
} else if (“–enable-lazy-preload”.equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) { //获取支持的架构列表
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);//根据socketName判断是否是primaryZygote,可能还有secondZygote

if (abiList == null) { //如果支持架构为空,直接抛出异常
throw new RuntimeException(“No ABI list supplied.”);
}

// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin(“ZygotePreload”);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}

// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin(“PostZygoteInitGC”);
gcAndFinalize(); //调用ZygoteHooks.gcAndFinalize()进行垃圾回收
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false, 0);

Zygote.initNativeState(isPrimaryZygote);//jni调用初始化zygote的状态,是否为isPrimaryZygote

ZygoteHooks.stopZygoteNoThreadCreation(); //结束zygote创建,其实内部是调用runtimezygote_no_threads_赋值为false,为创建本地线程做准备

zygoteServer = new ZygoteServer(isPrimaryZygote); //创建zygoteServer,为其他进程初始化创建时与zygote通信做准备

if (startSystemServer) { //判断是否需要startSystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//通过fork的方式开启zygote的子进程,systemServer,并返回一个Runnale对象
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {//如果是zygote进程,则r==null,如果不是zygote进程,也就是systemServer进程,则执行下面的代码
r.run();
return;
}
}

Log.i(TAG, “Accepting command socket connections”);

// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList); //zygote进程进入死循环中,来获取子进程发送的消息
} catch (Throwable ex) {
Log.e(TAG, “System zygote died with exception”, ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket(); //如果发生异常,则说明zygote初始化失败,zygoteServer也需要关闭
}
}

// We’re in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}

zygote的大概流程我们已经梳理完了,现在我们来总结一下

  1. 解析对应的zyogte.rc脚本
  2. 调用app_process/appMain.cpp
  3. 设置进程名为zygote
  4. 调用zygoteInit.java初始化zygote进程
  5. JNI调用zygoteInit.cpp完成进程创建
  6. 调用runSelectionLoop(),接收其他进程发送的消息创建子进程

Zygote是如何fork出SystemServer的

我们都知道,Android系统中,zyogte进程是Java世界的首个进程(init进程为头号进程),是直接通过exec的系统调用创建的,其他的进程,包括system_server,都是zygote进程的子进程,那我们接下来从源码的角度来看一下,zygote是如何forksystem_server

public static void main(String argv[]) {

if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) { //如果r不为空,说明是system_server进程
r.run(); //调用其run方法
return;
}
}


}

}

由上面的分析我们看到,根据zygote.rc的参数,解析出是否需要startSystemServer,如果为true,则调用forkSystemServer来fork出子进程SystemServer,并且执行其返回的Runnable的run()方法,我们先来看看forkSystemServer具体做了什么

/**

  • Prepare the arguments and forks for the system server process.
  • 为forkSystemServer进程准备参数,并且创建system server进程
  • @return A {@code Runnable} that provides an entrypoint into system_server code in the child
  • process; {@code null} in the parent.
    /
    private static Runnable forkSystemServer(String abiList, String socketName,
    ZygoteServer zygoteServer) {
    //Linux使用POSIX capabilities代替传统的信任状模型
    long capabilities = posixCapabilitiesAsBits( //设置进程权能
    OsConstants.CAP_IPC_LOCK, //允许锁定共享内存片段
    OsConstants.CAP_KILL, //允许对不属于自己的进程发送信号
    OsConstants.CAP_NET_ADMIN, // 允许执行网络管理任务:接口、防火墙和路由等
    OsConstants.CAP_NET_BIND_SERVICE, //允许绑定到小于1024的端口
    OsConstants.CAP_NET_BROADCAST, //允许网络广播和多播访问
    OsConstants.CAP_NET_RAW, //允许网络广播和多播访问
    OsConstants.CAP_SYS_MODULE, //插入和删除内核模块
    OsConstants.CAP_SYS_NICE, //允许提升优先级,设置其它进程的优先级
    OsConstants.CAP_SYS_PTRACE, //允许配置进程记帐
    OsConstants.CAP_SYS_TIME, //允许改变系统时钟
    OsConstants.CAP_SYS_TTY_CONFIG, //允许配置TTY设备
    OsConstants.CAP_WAKE_ALARM,
    OsConstants.CAP_BLOCK_SUSPEND
    );
    /
    Containers run without some capabilities, so drop any caps that are not available. */
    StructCapUserHeader header = new StructCapUserHeader(
    OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
    StructCapUserData[] data; //用户权能数据
    try {
    data = Os.capget(header); //获取进程权能,存储到data中
    } catch (ErrnoException ex) {
    throw new RuntimeException(“Failed to capget()”, ex);
    }
    capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

/* Hardcoded command line to start the system server */
/使用硬编码的方式定义出启动system server的参数字符串args/
String args[] = {
“–setuid=1000”, //用户id
“–setgid=1000”,//用户组id
“–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”, //进程niceName
    “–runtime-args”,
    “–target-sdk-version=” + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    “com.android.server.SystemServer”,
    };
    ZygoteArguments parsedArgs = null;

int pid; //processId,进程id

try {

parsedArgs = new ZygoteArguments(args); 创建ZygoteArguments对象,把args解析为需要的参数
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);

boolean profileSystemServer = SystemProperties.getBoolean(
“dalvik.vm.profilesystemserver”, false); //跟Art虚拟机相关,暂时不做深究
if (profileSystemServer) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}

/* Request to fork the system server process */
pid = Zygote.forkSystemServer( //fork创建SystemServer
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) { //pid为0,则说明是zygote进程,进行最后的收尾工作
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}

return null;
}

代码最后调用了Zygote.forkSystemServer()来创建SystemServer,我们接着来跟一下

public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();//内部调用ART的Runtime对zygote的线程池的线程进行清理
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer( //JNI调用,真正创建systemServer进程的函数
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}

接着跟下去,到c++的本地代码中 zygote.cpp

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

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

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

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

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

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

最后附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总)

面试成功其实是必然的,因为我做足了充分的准备工作,包括刷题啊,看一些Android核心的知识点,看一些面试的博客吸取大家面试的一些经验,下面这份PDF是我翻阅了差不多1个月左右一些Android大博主的博客从他们那里取其精华去其糟泊所整理出来的一些Android的核心知识点, 全部都是精华中的精华,我能面试到现在资深开发人员跟我整理的这本Android核心知识点有密不可分的关系,在这里本着共赢的心态分享给各位朋友。

这份PDF囊括了JVM,Java集合,Java多线程并发,Java基础,生命周期,微服务, 进程,Parcelable 接口,IPC,屏幕适配,线程异步,ART,架构,Jetpack,NDK开发,计算机网络基础,类加载器,Android 开源库源码分析,设计模式汇总,Gradle 知识点汇总…

由于篇幅有限,就不做过多的介绍,大家请自行脑补

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.youkuaiyun.com/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值