Dalvik VM进程系统(二):分析Zygote的启动过程,2024大厂Android开发面试总结+解答

本文详细介绍了Android中的Zygote进程如何注册Socket、预加载类和资源,以及启动SystemServer的过程。重点讨论了Zygote的Socket通信机制和SystemServer的权限设置、参数传递,以及Zygote如何监听Socket并启动应用进程。
摘要由CSDN通过智能技术生成

private static void registerZygoteSocket(String socketName) {

if (sServerSocket == null) {

int fileDesc;

final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

try {

String env = System.getenv(fullSocketName);

fileDesc = Integer.parseInt(env);

} catch (RuntimeException ex) {

throw new RuntimeException(fullSocketName + " unset or invalid", ex);

}

try {

FileDescriptor fd = new FileDescriptor();

fd.setInt$(fileDesc);

//不是使用IP和端口、而是使用fd创建socket

sServerSocket = new LocalServerSocket(fd); //1

} catch (IOException ex) {

throw new RuntimeException(

“Error binding to local socket '” + fileDesc + “'”, ex);

}

}

}

注释1处用来创建LocalServerSocket,也就是服务端的Socket。当Zygote进程将SystemServer进程启动后,就会在这个服务端的Socket上来等待ActivityManagerService请求Zygote进程来创建新的应用程序进程。

预加载类和资源


ZygoteInit#preload()

static void preload() {

beginIcuCachePinning();

preloadClasses(); //加载所需的各种class文件

preloadResources(); //加载资源文件

preloadOpenGL(); //初始化OpenGL

preloadSharedLibraries(); //加载系统Libraries

preloadTextResources(); //加载文字资源

// Ask the WebViewFactory to do any initialization that must run in the zygote process,

// for memory sharing purposes.

WebViewFactory.prepareWebViewInZygote(); //初始化WebView

endIcuCachePinning();

warmUpJcaProviders();

Log.d(TAG, “end preload”);

}

启动SystemServer进程


ZygoteInit#startSystemServer()

private static boolean startSystemServer(String abiList, String socketName)

throws MethodAndArgsCaller, RuntimeException {

long capabilities = posixCapabilitiesAsBits(

OsConstants.CAP_IPC_LOCK,

OsConstants.CAP_KILL,

OsConstants.CAP_NET_ADMIN,

OsConstants.CAP_NET_BIND_SERVICE,

OsConstants.CAP_NET_BROADCAST,

OsConstants.CAP_NET_RAW,

OsConstants.CAP_SYS_MODULE,

OsConstants.CAP_SYS_NICE,

OsConstants.CAP_SYS_RESOURCE,

OsConstants.CAP_SYS_TIME,

OsConstants.CAP_SYS_TTY_CONFIG

);

/* Containers run without this capability, so avoid setting it in that case */

if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {

capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);

}

/* Hardcoded command line to start the system server */

/* 1 */

String args[] = {

“–setuid=1000”,

“–setgid=1000”,

“–setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010”,

“–capabilities=” + capabilities + “,” + capabilities,

“–nice-name=system_server”,

“–runtime-args”,

“com.android.server.SystemServer”,

};

ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {

/* 2 */

parsedArgs = new ZygoteConnection.Arguments(args);

/** 打开系统调试属性*/

ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);

ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* 3 */

// 请求fork SystemServer进程

pid = Zygote.forkSystemServer(

parsedArgs.uid, parsedArgs.gid,

parsedArgs.gids,

parsedArgs.debugFlags,

null,

parsedArgs.permittedCapabilities,

parsedArgs.effectiveCapabilities);

} catch (IllegalArgumentException ex) {

throw new RuntimeException(ex);

}

// pid为0表示子进程,即SystemServer进程,从此SystemServer进程与Zygote进程分道扬镳

if (pid == 0) {

if (hasSecondZygote(abiList)) {

waitForSecondaryZygote(socketName);

}

handleSystemServerProcess(parsedArgs); //4

}

return true;

}

注释1处用来创建args数组,这个数组用来保存SystemServer的启动参数,其中可以看出SystemServer进程的用户id和用户组id被设置为1000;并且拥有用户组10011010,1018、1021、1032、30013010的权限;进程名为system_server;启动的类名为com.android.server.SystemServer。

注释2处将args数组封装成Arguments对象并供注释3的forkSystemServer函数调用。

注释3处调用Zygote的forkSystemServer,主要通过fork函数在当前进程创建一个子进程(也就是SystemServer进程),如果返回的pid 为0,也就是表示在新创建的子进程中执行的,则执行注释4处的handleSystemServerProcess,反射调用SystemServer#main(),来启动SystemServer进程。

具体handleSystemServerProcess是如何启动SystemServer进程的,请看Framework学习(三)SyetemServer进程启动过程这篇文章。

监听Socket,启动应用进程


ZygoteInit#runSelectLoop()

启动SystemServer进程后,最后进入runSelectLoop函数,如下所示。

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {

ArrayList fds = new ArrayList();

ArrayList peers = new ArrayList();

fds.add(sServerSocket.getFileDescriptor()); //1

peers.add(null);

while (true) {

StructPollfd[] pollFds = new StructPollfd[fds.size()];

for (int i = 0; i < pollFds.length; ++i) { //2

pollFds[i] = new StructPollfd();

pollFds[i].fd = fds.get(i);

pollFds[i].events = (short) POLLIN;

}

try {

Os.poll(pollFds, -1);

} catch (ErrnoException ex) {

throw new RuntimeException(“poll failed”, ex);

}

for (int i = pollFds.length - 1; i >= 0; --i) { //3

if ((pollFds[i].revents & POLLIN) == 0) {

continue;

}

if (i == 0) {

ZygoteConnection newPeer = acceptCommandPeer(abiList); //4

peers.add(newPeer);

fds.add(newPeer.getFileDesciptor());

} else {

boolean done = peers.get(i).runOnce(); //5

if (done) {

peers.remove(i);

fds.remove(i);

}

}

}

}

}

注释1处中的sServerSocket就是我们在registerZygoteSocket函数中创建的服务端Socket,调用sServerSocket.getFileDescriptor()用来获得该Socket的fd字段的值并添加到fd列表fds中。接下来无限循环用来等待ActivityManagerService请求Zygote进程创建新的应用程序进程。

注释2处通过遍历将fds存储的信息转移到pollFds数组中。

注释3处对pollFds进行遍历。

注释4如果i==0则说明服务端Socket与客户端连接上,也就是当前Zygote进程与ActivityManagerService建立了连接,则通过acceptCommandPeer函数得到ZygoteConnection类并添加到Socket连接列表peers中,接着将该ZygoteConnection的fd添加到fd列表fds中,以便可以接收到ActivityManagerService发送过来的请求。

注释5如果i的值大于0,则说明ActivityManagerService向Zygote进程发送了一个创建应用进程的请求,则调用ZygoteConnection的runOnce函数来创建一个新的应用程序进程。并在成功创建后将这个连接从Socket连接列表peers和fd列表fds中清除。

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

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

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

img

img

img

img

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司20年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

架构技术进阶脑图、Android开发面试专题资料**,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-h3Ahx69j-1712485007329)]

【算法合集】

[外链图片转存中…(img-5PMc23f9-1712485007330)]

【延伸Android必备知识点】

[外链图片转存中…(img-5Mtf5eCx-1712485007330)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值