笔记: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()开始的.与启动普通进程的差别 ...
随机推荐
- 关于微信小程序appsecret保护的问题
本地后端代码中通常会配置 appid 和 appsecret,直接 push 到 公有 git 库会导致所有人可见.但其他人由于不是开发者有了别的项目的 secret 用处不大.但仍建议采用某种方法加 ...
- Odoo 堆积木似的软件构建
七雄争霸秦国一统天下,统一货币度量衡,从此天下统一... 假设在未来的某天,有一款开源的系统平台能将国内的企业管理软件市场进行统一,规范市场,标准开发,所有系统的集成创建通过市场开放的应用独立安装搭建 ...
- java-27 Properties类的使用
1.Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载.属性列表中每个键及其对应值都是一个字符串. 2.方法 setProperty( ...
- CentOS开机提示kernel panic - not syncing: Attempted to kill init! 解决方法
1.重新启动linux 系统,看见如图见面迅速按E键 2.看见如图界面在按E键编辑 3.如图界面使用上下键选择第二个在按E键 4.在最后一行后面添加 enforcing=0 按回车保存退出 5.在此 ...
- CentOS 7 建立svn仓库 远程连接
首先安装svn (后补) mikdir /usr/local/svn_repertory # 创建svn大仓库用于存放所有项目代码 cd /usr/local/svn_repertory # 进 ...
- GUI学习之三——QObject学习总结
鉴于PyQt控件的继承关系,我们先学习PyQt控件的基类——QObject. 一.所有的QT对象的基类 我们先看一下PyQt里空间的继承关系,稍微改一下代码,显示出继承关系 from PyQt5.Q ...
- IDEA debugger模式下启动慢
很可能是因为代码里面有端点造成的. 点击如下图的重叠红点,找到对应端点点掉就可以了.
- Linux 网络编程 入门-常用函数
网络连接无外乎服务器和客户端两方面的编程. 对于服务器大致的流程是:1---调用socket函数创建套接字 2---调用bind函数分配IP地址和端口号 3---调用listsen函数将套接字转为可接 ...
- spark原理
SparkContext将应用程序代码分发到各Executors,最后将任务(Task)分配给executors执行 Application: Appliction都是指用户编写的Spark应用程序, ...
- CSS追加笔记
box-shadow 属性向框添加一个或多个阴影. 语法 box-shadow: h-shadow v-shadow blur spread color inset;注释:box-shadow 向框添 ...