写点什么

Android-Framework 学习笔记(二)Zygote 进程启动过程,移动互联网 app 开发

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

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


ZygoteInit#main()


public static void main(String argv[]) {...


try {//设置 DDMS 可用 RuntimeInit.enableDdms(); //1//初始化启动参数 boolean startSystemServer = false;String socketName = "zygote";String abiList = null;//2for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = 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)) {socketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}


if (abiList == null) {throw new RuntimeException("No ABI list supplied.");}//注册 Zygote 用的 SocketregisterZygoteSocket(socketName); //3//预加载类和资源 preload(); //4...//启动 SystemServer 进程 if (startSystemServer) {startSystemServer(abiList, socketName); //5}


//监听 socket,启动新的应用进程


runSelectLoop(abiList); //6closeServerSocket();} catch (MethodAndArgsCaller caller) {//通过反射调用 SystemServer#main()caller.run();} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}


注释 1 设置 DDMS 可用,可以发现 DDMS 启动的时机还是比较早的,在整个 Zygote 进程刚刚开始要启动的时候就设置可用了。注释 2 的循环主要是解析 main 方法的参数获取是否需要启动 SystemService 进程,获取 abi 列表,获取 scoket 连接名称 。(这里需要注意的是:android 系统中进程之间通讯的方式是 Binder,但是有一个例外是 SystemService 进程与 Zygote 进程之间是通过 Socket 的方式进行通讯的)注释 3 处通过 registerZygoteSocket 函数来创建一个 Server 端的 Socket,这个 name 为”zygote”的 Socket 用来等待 ActivityManagerService 来请求 Zygote 来创建新的应用程序进程。注释 4 处用来预加载类和资源。注释 5 处用来启动 SystemServer 进程,这样系统的关键服务也会由 SystemServer 进程启动起来。注释 6 处调用 runSelectLoop 函数监听 socket 来等待客户端请求。由此可见,ZygoteInit 的 main 函数主要做了 4 件事(注释 3、4、5、6),接下来我们对主要的事件一一进行分析。

注册 Server 端的 Socket

ZygoteInit#registerZygoteSocket()


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 创建 socketsServerSocket = 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(); //初始化 OpenGLpreloadSharedLibraries(); //加载系统 LibrariespreloadTextResources(); //加载文字资源// Ask the WebViewFactory to do any initialization that must run in the zygote process,// for memory sharing purposes.WebViewFactory.prepareWebViewInZygote(); //初始化 WebViewendIcuCachePinning();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.app


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


lyInvokeWithSystemProperty(parsedArgs);


/* 3 */// 请求 fork SystemServer 进程 pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android-Framework学习笔记(二)Zygote进程启动过程,移动互联网app开发