笔记: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 main
String 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 {
@Override
public 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编写)
笔记:Zygote和SystemServer进程启动过程的更多相关文章
- Android系统启动流程(三)解析SystemServer进程启动过程
1.Zygote启动SystemServer进程 在上一篇文章中我们讲到在ZygoteInit.java的startSystemServer函数中启动了SyetemServer进程,如下所示. fra ...
- Zygote及System进程启动
1. init 根据init.rc 运行 app_process, 并携带‘--zygote' 和 ’--startSystemServer' 参数. 2. AndroidRuntime.cpp: ...
- Android应用程序进程启动过程(前篇)
在此前我讲过Android系统的启动流程,系统启动后,我们就比较关心应用程序是如何启动的,这一篇我们来一起学习Android7.0 应用程序进程启动过程,需要注意的是“应用程序进程启动过程”,而不是应 ...
- Android应用程序进程启动过程的源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...
- Android应用程序进程启动过程(后篇)
前言 在前篇中我们讲到了Android应用程序进程启动过程,这一篇我们来讲遗留的知识点:在应用程序进程创建过程中会启动Binder线程池以及在应用程序进程启动后会创建消息循环. 1.Binder线程池 ...
- Android系统启动流程(二)解析Zygote进程启动过程
1.Zygote简介 在Android系统中,DVM(Dalvik虚拟机).应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器.它通过 ...
- Android系统启动流程(一)解析init进程启动过程
整体流程大致如下: 1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ...
- Linux进程启动过程简析
朱宇轲 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 今天,我们将通过 ...
- Android(java)学习笔记161:Framework运行环境之启动SystemServer进程
SystemServer进程是zygote孵化出的第一个进程,该进程是从ZygoteInit.java的main函数中调用startSystemServer()开始的.与启动普通进程的差别 ...
随机推荐
- django xadmin查找当前用户所在组
self.request.user:获取当前登录用户用户名 qs = Group.objects.get(user=self.request.user)获取当前登录用户所在组qs.name 获取当前登 ...
- 登录界面,body上有背景图,点击输入框时,弹出的手机键盘会把背景图顶变形,而且会把footer顶上去
js: //防止背景图被手机键盘压缩变形 $(document).ready(function () { $('body').css({'height':$(window).height()}) }) ...
- 把多个字符串里面的项写到不同的对象中,然后在push到一个数组中
otherUserNames: "甲,乙,丙,丁"otherUserIds: "10008750,10008711,10003348,10008747" oth ...
- python 获取流文件 大小
buffer_file_content=u"流文件内容" file_size = len(buffer_file_content)/ #kb
- Mysql必知必会 检索数据
检索数据 SELECT 语句 为了使用SELECT检索表数据,必须至少给出两条信息--想选择什么,以及从什么地方选择 功能 语句 备注 检索单个列 SELECT col_1 FROM table_na ...
- 部落划分Group[JSOI2010]
--BZOJ1821 Description 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生 ...
- linux RCU机制
参考资料: https://www.cnblogs.com/qcloud1001/p/7755331.html https://www.cnblogs.com/chaozhu/p/6265740.ht ...
- Numpy安装
Python官网上的发行版是不包含Numpy模块的. 1.使用已有的发起行版本 对于许多用户,尤其是在Windows上,最简单的方法就是下载以下的Python发行版,他们包涵了所有的关键包(包括Num ...
- JSP 页面跳转的实现方法
客户端跳转 1. 使用 href 超链接标记 <a href="new.jsp">跳转</a> 2. 使用表单提交完成跳转 <form actio ...
- Maven中阿里云私服配置
在国内maven仓库连接速度太慢 ,虽然对于很多互联网企业和大中型软件公司,建个镜像是分分钟的事.但对于个人开发者确实是个问题.解决办法可以用阿里云的MAVEN私服.有两种方法: 1.在$MAVEN_ ...