笔记:Zygote和SystemServer进程启动过程

简述

Android设备启动过程中,先是Linux内核加载完,接着Android中的第一个进程init启动,它会启动一些需要开机启动的进程。
Zygote就是进程init启动起来的。Android中所有应用程序进程,以及运行系统关键服务的System进程都是由Zygote创建的。它通过复制自身的形式创建其它进程。Zygote在启动时会在内部创建一个虚拟机实例,因此,通过复制Zygote得到的其它应用程序进程和System进程都可以快速地在内部获得一个虚拟机地拷贝。Zygote启动完成后就立即将System进程启动,以便各种关键服务被启动运行。

Zygote的启动

它以服务的形式被启动。

创建虚拟机

进程内创建一个虚拟机实例,并注册一系列JNI方法。
frameworks/base/core/jni/AndroidRuntime.cpp

/* start the virtual machine. */
startVM(&mJavaVM, &env);
/* Register android functions. */
startReg(env);

接下来执行“com.android.internal.os.ZygoteInit”Java类的main方法继续执行启动。

ZygoteInit.main

package com.android.internal.os;
import android.net.LocalServerSocket;
...
public class ZygoteInit {private static LocalServerSocket sServerSocket;public static void main(String argv[]) {...registerZygoteSocket();...if (argv[1].equals("true")) {startSystemServer();} else if (!argv[1].equals("false")) {throw new RuntimeException(argv[0] + USAGE_STRING);}...if (ZYGOTE_FORK_MODE) {runForkMode();} else {runSelectLoopMode();}...closeServerSocket();...}
}

创建Socket

Zygote调用registerZygoteSocket();创建一个LocalServerSocket sServerSocket的Server端Socket,等待以后运行在System进程中的服务ActivityManagerService创建的Client端Socket连接,然后通过Socket进程间通信通知Zygote创建新的应用程序进程。

创建System进程

/*** Prepare the arguments and fork for the system server process.*/
private static boolean startSystemServer()throws MethodAndArgsCaller, RuntimeException {/* Hardcoded command line to start the system server */String args[] = new String[] {"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006","--capabilities=130104352,130104352","--rlimit=8,","--runtime-init","--nice-name=system_server","com.android.server.SystemServer",};...ZygoteConnection.Arguments parsedArgs = null;int pid;try {parsedArgs = new ZygoteConnection.Arguments(args);/* Request to fork the system server process */pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, debugFlags, rlimits,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}/* For child process */if (pid == 0) {handleSystemServerProcess(parsedArgs);}return true;
}

变量args保存启动System进程的参数。
Zygote.forkSystemServer()复制当前进程来创建子进程。
handleSystemServerProcess()继续处理System进程的启动。

轮询等待AMS请求创建App进程

private static void runSelectLoopMode() throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList();ArrayList<ZygoteConnection> peers = new ArrayList();FileDescriptor[] fdArray = new FileDescriptor[4];fds.add(sServerSocket.getFileDescriptor());peers.add(null);while (true) {...try {fdArray = fds.toArray(fdArray);index = selectReadable(fdArray);} catch (IOException ex) {throw new RuntimeException("Error in select()", ex);}if (index < 0) {throw new RuntimeException("Error in select()");} else if (index == 0) {ZygoteConnection newPeer = acceptCommandPeer();peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {boolean done;done = peers.get(index).runOnce();if (done) {peers.remove(index);fds.remove(index);}}}
}/*** Waits for and accepts a single command connection. Throws* RuntimeException on failure.*/
private static ZygoteConnection acceptCommandPeer() {try {return new ZygoteConnection(sServerSocket.accept());} catch (IOException ex) {throw new RuntimeException("IOException during accept()", ex);}
}

无限循环,等待来自AMS创建的Socket连接。
sServerSocket在fds[0]位置。
每当accept()返回一个连接后,将对应此连接的newPeer.getFileDesciptor()套接字描述添加到fds(第0位置后),下一次读取到数据时,若在fds[0]以后的,说明是前面的newPeer连接收到的AMS的创建新应用程序进程的请求。
runOnce()用来处理AMS创建新应用程序进程的请求。

System进程的启动

ZygoteInit.handleSystemServerProcess()执行System进程的启动操作。

ZygoteInit.handleSystemServerProcess()

private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {closeServerSocket();/** Pass the remaining arguments to SystemServer.* "--nice-name=system_server com.android.server.SystemServer"*/RuntimeInit.zygoteInit(parsedArgs.remainingArgs);/* should never reach here */
}

Zygote复制自身创建的子进程做为System进程,这样它得到了Zygote的Server Socket,但是用不到,所以第一句closeServerSocket()关闭此套接字。

RuntimeInit.zygoteInit

package com.android.internal.os;public class RuntimeInit {public static final void zygoteInit(String[] argv)throws ZygoteInit.MethodAndArgsCaller {...commonInit();zygoteInitNative();...// Remaining arguments are passed to the start class's static mainString startClass = argv[curArg++];String[] startArgs = new String[argv.length - curArg];System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);invokeStaticMain(startClass, startArgs);}  
}

zygoteInitNative()在System进程中启动一个Binder线程池。
RuntimeInit.invokeStaticMain()静态方法调用"com.android.server.SystemServer"的main方法。

SystemServer.main

传递调用native方法init1():

class SystemServer {/*** This method is called from Zygote to initialize the system. This will cause the native* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back* up into init2() to start the Android services.*/native public static void init1(String[] args);
}

init1()的工作:
注册Service Manager的死亡通知:调用binderDied()。System进程执行kill结束自己。

创建SurfaceFlinger、和SensorService两个服务。

返回SystemServer.init2()继续启动java语言开发的系统服务。

SystemServer.init2

public static final void init2() {Thread thr = new ServerThread();thr.setName("android.server.ServerThread");thr.start();
}

ServerThread继承自Thread。

ServerThread.run

class ServerThread extends Thread {@Overridepublic void run() {Looper.prepare();...// Critical services...try {...Slog.i(TAG, "Activity Manager");context = ActivityManagerService.main(factoryTest);...Slog.i(TAG, "Package Manager");pm = PackageManagerService.main(context,factoryTest != SystemServer.FACTORY_TEST_OFF);...Slog.i(TAG, "Content Manager");ContentService.main(context,factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);...Slog.i(TAG, "Window Manager");wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);ServiceManager.addService(Context.WINDOW_SERVICE, wm);...((ActivityManagerService)ServiceManager.getService("activity")).setWindowManager(wm);...} catch (RuntimeException e) {Slog.e("System", "Failure starting core service", e);}...Looper.loop();Slog.d(TAG, "System ServerThread is exiting!");}
}

启动各个Service然后注册到ServiceManager。
各个服务都使用Binder和其它服务使用者进程进行就行交互。

(本文使用Atom编写)

转载于:https://www.cnblogs.com/everhad/p/6290855.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/417393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C中执行指令/程序

//执行并等待程序运行完毕system("E:\\code\\Test\\Debug\\MyEditor.exe"); //暂停system("pause");

python中怎么精确20位_Python中的精确处理

Python可以使用不同的函数来处理浮点数的精度。数学模块中定义了大多数用于精确处理的函数。因此&#xff0c;要使用它们&#xff0c;首先我们必须将math模块导入到当前命名空间中。import math现在&#xff0c;我们将看到一些用于精确处理的功能。该trunc()方法该trunc()方法用…

Axure 共享强制签出签入

签出时点击不签出编辑全部——确定修改后签入时点击全部偷偷签出——确定注意一定要修改后&#xff0c;否则无法检测到修改&#xff0c;不会执行签入

ubuntu mysql混合开发_mysql5.7主从同步 ubuntu

实现环境&#xff1a;| System   | mysql     | ip       ||主ubuntu  | mysql-5.7.24 | 10.192.209.122 ||从ubuntu  | mysql-5.7.39 | 10.192.209.43 |注&#xff1a;从服务器的mysql版本最好和主服务器相同&#xff0c;或者大于主服务器版本MySQL主…

关于逐项作用函数的用法

关于逐项作用函数的用法讲一下Thread这个函数的用法&#xff0c;其中后面两个用法很好用&#xff0c;也常常被忽略。用法一&#xff1a;比较常用用法二&#xff1a;我觉得这一种是很实用的有拓展的方法用法三&#xff1a;构造一种映射关系&#xff0c;在配合 Association[] 关联…

IIS Service Unavailable问题

应用程序池被两个.Net版本的网站使用&#xff0c;不同.Net版本的网站应该用不同的应用程序池&#xff0c;服务器上最好是每个网站一个应用程序池&#xff0c;避免某个网站导致应用程序池停止运行而影响其他网站。

博客园的博客终于开通了

楼主来了博客园不知不觉已经1年5个月&#xff0c;实际上早就知道博客园的存在&#xff0c;一直没注册。 在园子里&#xff0c;感觉时间过得好快&#xff0c;期间学习到了很多东西&#xff0c;唯一不足的是没有及时记下心得和笔记。 现在有些知识点又忘得差不多&#xff0c;好记…

linux搭建java开发环境_linux中搭建java开发环境

今天试着在Linux下面搭建java开发环境&#xff0c;现总结一下具体步骤。1、JDK的安装1.6 版本cd /optmkdir java执行下面命令安装JDK(首先创建/opt/java目录)tar -xvf jdk-7u7-linux-i586.tar.gz -C /opt/javaln -s /opt/java/jdk1.7.0_09 /opt/java/jdk 创建一个链接vi /etc/f…

js cookie操作

//cookie操作3个方法//设置cookiefunction setCookie(name, value) {var argv setCookie.arguments;var argc setCookie.arguments.length;var expires (argc > 2) ? argv[2] : null;if (expires ! null) {var LargeExpDate new Date();LargeExpDate.setTime(LargeExpD…

SQLServer常用系统视图

数据库 sys.databases 数据库文件 sys.master_files对象 sys.objects表 sys.tables存储过程 sys.procedures列 sys.columns架构 sys.schemas索引 sys.indexes

java8多线程_Java8——三种多线程方式

1、多线程的使用方式1.1、继承Thread类继承Thread并重写run()方法&#xff0c;Thread类中的start方法会去调用系统的方法执行相应的线程。实际上Thread也是实现了Runable接口的&#xff0c;从该类的文档中我们能找到。1.2、实现Runable接口实现Runable接口&#xff0c;并重写ru…

重构指南 - 引入参数对象(Introduce Parameter Object)

当一个方法的参数超过3个以上&#xff0c;就可以考虑将参数封装成一个对象。将参数封装成对象后提高了代码的可读性&#xff0c;并且该参数对象也可以供多个方法调用&#xff0c;以后如果增加删除参数&#xff0c;方法本身不需要修改&#xff0c;只需要修改参数对象就可以。重构…

git clone 时候出现Please make sure you have the correct access rights and the repository exists.

输入 git clone 命令时出现Please make sure you have the correct access rights and the repository exists.错误&#xff0c;出现改问题的原因是git服务器没有存储本地ssh密钥。 解决步骤&#xff1a; 1. 删除 .ssh 文件夹【C:\Users\(本地用户名)\.ssh】 中的 known_host…

java io之图片存取

一&#xff1a;建表 二&#xff1a;获取数据库连接 1&#xff1a;导入mysql的驱动jar包&#xff0c;mysql-connector-java-5.1.8-bin.jar 2&#xff1a;写代码连接数据库&#xff0c;如下&#xff1a; 1 /**2 * 3 */ 4 package com.hlcui.file; 5 6 import java.sql.Connec…