版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com
zygote
进程在 Android 开发中属于比较底层的内容,然而要透彻的理解 AMS、WMS 和 IPC 等,不可避免的要先理解zogyte
进程,因此本文即作为对自己的学习记录,也想分享出来和遇到同样问题的读者交流。
在正式内容开始之前,我建议读者朋友下载部分源代码备用,分别是:
platform/framework/base
platform/system/core
platform/packages/apps/Launcher3
我们可以到 Android 源码托管站下载:https://android.googlesource.com/,可以下载具体某个模块源代码,可以指定分支或者 tag,需要翻阅 GFW。
另外如果你没有翻阅 GFW 的条件的话,可以使用清华大学镜像源:
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/
例如,现在我们从 Terminal 进入~/Workspance/Android
目录下,然后分别下载上述三个模块oreo-release
分支的源代码:
$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/frameworks/base platform_framework_base
...
$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/system/core platform_system_core
...
$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/packages/apps/Launcher3 platform_packages_apps_Launcher3
特别声明:本文出现的源代码,为了更加简洁清晰,部分代码经过大量的精简,读者阅读本文时,如果有条件,最好配合源代码,以免产生误解。
另外,纠正一个无伤大雅的小问题,我们经常说的init
进程、zygote
进程和system_server
进程,它们的名字如上所写,不是大写,也不是驼峰式写法,比如这些写法是不正确的:
Init进程,正确的应该是:init进程
Zygote进程,正确的应该是:zygote进程
SystemServer进程,正确的应该是:system_server进程
init.rc
配置文件的作用和运行流程init.zygote.rc
配置文件的含义和作用ZygoteInit.java
初始化zygote
进程的过程ZygoteInit.java
启动system_server
进程的过程SystemServer.java
初始化system_server
进程的过程zygote
进程等待 Socket 客户端的请求Android 系统是基于 Linux 内核的,Linux 系统中的进程都是 init
进程的子进程,Android 的zygote
进程也是在系统启动的过程,由init
进程创建的。本小节要分析从系统启动后代码是如何执行到 zygote
相关逻辑块的,然后由此引出zygote
的启动过程分析。
系统启动时kernel/init/main.c
文件中的kernel_init()
函数会做一些硬件相关的基础工作,比如 CPU 初始化和内存初始化等,然后会执行platform/system/core
目录下的init
程序,该程序即 Android 的init
进程对应的程序。该程序的对应代码是platform/system/core/init.cpp
,打开该文件并找到它的入口函数:
// 注意这两行引入
#include "property_service.h"
#include "service.h"
int main(int argc, char** argv) {
... // 一些必要的环境变量配置和启动其他Linux进程
// 执行在头部引入的property_service.h的start_property_service()函数
start_property_service();
// 解析配置文件
Parser& parser = Parser::GetInstance();
// 解析service
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
parser.ParseConfig("/init.rc");
...
ActionManager& am = ActionManager::GetInstance();
... // 配置am命令参数
while (true) {
// 使用epoll机制 + 死循环,使init进程一直运行,类似Looper#loop()
// 默认一直阻塞,直到有事情需要做被唤醒
int epoll_timeout_ms = -1;
if (...) {
am.ExecuteOneCommand();
// 一些赋值逻辑,可能是0
epoll_timeout_ms = ...;
}
// 调用epoll_wait使init进程沉睡或者...
epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms);
}
return 0;
}
我们会发现该函数中解析了位于platform/system/core/rootdir/init.rc
的初始化配置文件,我摘抄出了与zygote
进程相关的部分代码:
import /init.${ro.zygote}.rc
...
# 当电源键被按住的时候执行 property
on property:sys.boot_from_charger_mode=1
class_stop charger
trigger late-init
# 挂载文件系统并启动核心系统服务
on late-init
...
# 调用zygote-start
trigger zygote-start
...
trigger early-boot
trigger boot
# 在init.rc中调用zygote-start解除zygote的启动阻塞
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
上述配置的代码类似 C 语言风格,每一个on
和后边的定义我们暂且把它叫做函数,当手机处于关机状态时,我们摁住电源键开机,init
进程执行到这里时,会调用property
函数,该函数做一些准备工作后,会调用late-init
函数,late-init
函数会做一些启动初始化相关的工作,完事以后会调用zygote-start
去执行init.zygote*.rc
,我们发现该配置文件在init.rc
文件头部被引入:
import /init.${ro.zygote}.rc
该文件被引入时有个ro.zygote
变量,它可以被理解为一个环境变量,该变量的值和设备的 CPU 平台相关,同样在./rootdir
目录下的可选项有:
init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc
为了一目了然简单清晰,我们选择init.zygote32.rc
来分析,init
进程执行到这里,根据init.zygote32.rc
的描述,会 fork zygote
进程,具体细节请看下一节。
打开init.zygote32.rc
文件后我们发现它的代码很简洁清晰:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
我们在代码开头看到了service
,在platform/core/init/README.md
中有对init
语法的描述,service
的语法是这样的:
service <name> <pathname> [ <argument> ]*
<option>
<option>
其中对service
的解释是:service
是init
退出时启动和重新启动的程序。我认为在这里,init
会先 fork 一个进程,会把该进程命名为zygote
,然后在该进程中执行/system/bin/app_process
程序,并且带上参数--zygote -- start-system-server
。
后面的socket
是为zygote
进程创建一个名称为"zygote"的socket
资源,在系统启动后,我们可以在/dev/socket
目录下发现一个名为“zygote”的文件。在本文中,该配置被执行完后我们会做这个 Socket 资源的验证。
接下来,我们把目光集中在zygote
进程接下来要执行的/system/bin/app_process
程序上,system/bin
一般用来存放系统命令类的程序,通过分析和查找,它对应的代码在platform/frameworks/base/cmds/app_process/app_main.cpp
文件中,接下来我们详细分析该文件。
上面讲到init
进程解析init.zygote.rc
后,会 forkzygote
进程,然后在zygote
进程中执行/system/bin/app_process
程序,执行该程序的目的是初始化zygote
进程。
接下来我们打开platform/frameworks/base/cmds/app_process/app_main.cpp
文件,来分析初始化zygote
进程时做了哪些事情,目光定位在main()
函数上:
int main(int argc, char* const argv[])
{
// 创建 AppRuntime的成员变量
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
// 解析运行时参数,赋值zygote和startSystemServer
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
if (!className.isEmpty()) {
...
} else {
...
if (startSystemServer) {
args.add(String8("start-system-server"));
}
}
if (zygote) {
// 调用 ZygoteInit#main()
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
上述代码,首先创建了一个AppRuntime
的局部成员变量,然后对入参进行了解析,根据对init.zygote32.rc
传入参数的分析,这里的zygote
变量和startSystemServer
的值均为true
,因此在最后调用AppRuntime#start()
函数时走了:
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
AppRuntime
类也定义在platform/frameworks/base/cmds/app_process/app_main.cpp
中:
class AppRuntime : public AndroidRuntime
{
...
};
发现AppRuntime
类继承于AndroidRuntime
,而AppRuntime
类中是没有start()
函数的,因此回到上方的main()
函数中,实际上当执行AppRuntime#start()
时实际上是执行了AndroidRuntime#start()
,下面我们来看看AndroidRuntime
类,它位于platform/frameworks/base/core/jni/AndroidRuntime.cpp
:
void AndroidRuntime::start(const char* className, ..., bool zygote)
{
static const String8 startSystemServer("start-system-server");
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
startVm(&mJavaVM, &env, zygote);
onVmCreated(env);
/*
* Register android functions.
*/
startReg(env);
/*
* We want to call main() with a String array with arguments in it.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
env->CallStaticVoidMethod(startClass, startMeth, strArray);
...
}
根据AndroidRuntime
名称和上述代码可以分析得出,该函数启动了 Android 系统运行时库,其中它主要做了三件事:
startVmVM()
函数启动虚拟机startReg()
函数注册 Android 的 Java 方法,其实在这里就是 JNI 方法com.android.internal.os.ZygoteInit#main()
方法,并把 fork zygote
进程时的参数传入用来辅助初始化zygote
进程此时,我们回到启动zygote
进程的地方回顾一下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
根据上述分析,此时调用句柄已经执行到com.android.internal.os.ZygoteInit#main()
,该类的 Java 文件位于platform/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
:
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
// 标记Zygote开始初始化,并Hook确保不创建其他线程
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote进入自己的进程组
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
...
boolean startSystemServer = false;
String socketName = "zygote";
// 解析参数,初始化局部变量
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
}
...
}
// 注册一个名为zygote的ServerSocket,
zygoteServer.registerServerSocket(socketName);
// 第一次启动时会预加载资源
if (!enableLazyPreload) {
...
preload(bootTimingsTraceLog);
}
...
// 停止Hook不创建其他线程,也就是说允许创建其他线程
ZygoteHooks.stopZygoteNoThreadCreation();
// 这里一定是true,启动SystemServer
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
// 运行zygote进程的select循环
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
}
在这个初始化过程中,做了不少准备工作,更加详细的过程请阅读上述代码注释和源码,我们这里总结以下我们需要着重关注的几件事:
ZygoteServer#registerServerSocket()
方法创建一个名为zygote
的 Socket 资源ZygoteInit#starSystemServer()
方法启动system_server
进程ZygoteInit#runSelectLoop()
方法循环接受 Socket 连接,在这里开始和 AMS 搭上边,其实这里就是循环等待 AMS 的连接和命令,更加详细的过程在下文中分析。上面说到ZygoteServer#registerServerSocket()
创建了一个名为zygote
的 Socket 资源,我们知道,Socket 是 IPC 通信的一种方式,该 Socket 资源在后期被用在和 AMS 等服务进行进程间通信。下面我们来看ZygoteServer#registerServerSocket()
的具体实现,ZygoteServer.java
位于com.android.internal.os.ZygoteServer.java
:
class ZygoteServer {
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
private LocalServerSocket mServerSocket;
ZygoteServer() {
}
void registerServerSocket(String socketName) {
if (mServerSocket == null) {
int fileDesc;
// fullSocketname的值是ANDROID_SOCKET_zygote
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
// 获取Socket名称对应的环境变量
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
// 根据环境变量创建文件描述符
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 根据文件描述符创建Socket
mServerSocket = new LocalServerSocket(fd);
}
}
}
请读者先看完上述代码的注释,上述代码中其他的因素都是确定的,只有 Socket 名称对应的环境变量是不确定的,这个环境变量指向的文件描述符的值是在文章开头的platform/system/init.cpp
创建的,在文章开头其实我已经标识出来了,但是大多数人应该不知道是干嘛用的,我们回到init.cpp
:
// 注意这两行引入
#include "property_service.h"
#include "service.h"
int main(int argc, char** argv) {
... // 一些必要的环境变量配置和启动其他Linux进程
// 执行在头部引入的property_service.h的start_property_service()函数
start_property_service();
// 解析配置文件
Parser& parser = Parser::GetInstance();
// 解析service
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
...
}
该函数中start_property_service()
会去创建 Socket 资源,下面我们一步步看这些相关的文件。
platform/system/core/init/property_service.cpp
中调用util#create_socket()
函数:
#include "util.h"
void start_property_service() {
property_set("ro.property_service.version", "2");
// 创建Socket连接
property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | ...);
...
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
platform/system/core/init/util.cpp
的create_socket()
函数会在ANDROID_SOCKET_DIR
常量指定的目录创建一个 Unix 的 Socket 资源,并通过ANDROID_SOCKET_ENV_PREFIX
常量加[name]
指定名称的环境变量向其他位置共享该文件描述符的值:
#include
/*
* create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
* ("/dev/socket") as dictated in init.rc. This socket is inherited by the
* daemon. We communicate the file descriptor's value via the environment
* variable ANDROID_SOCKET_ENV_PREFIX ("ANDROID_SOCKET_foo").
*/
int create_socket(const char *name, ...)
{
...
android::base::unique_fd fd(socket(PF_UNIX, type, 0));
...
return fd.release();
}
上述两个常量定义在platform/system/core/include/cutils/sockets.h
中:
#define ANDROID*SOCKET_ENV_PREFIX "ANDROID_SOCKET*"
#define ANDROID_SOCKET_DIR "/dev/socket"
如果你手里有个 Android 系统的设备,我们可以查看一下该文件:
Harrys-MacBook-Pro:Visit Harry$ adb shell
shell@cancro:/ $ cd /dev/socket
shell@cancro:/dev/socket $ ls
adbd
...
zygote
shell@cancro:/dev/socket $
在上述com.android.internal.os.ZygoteServer.java
中也能看到 Socket 资源的前缀常量,因此它在这里就获取到了名为ANDROID_SOCKET_zygote
的文件描述符,并在 Java 层创建了LocalServerSocket
的服务端 Socket 对象。
zygote
进程启动了 Java 层的LocalServerSocket
后,接着调用了ZygoteInit#starSystemServer()
启动system_server
进程。
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String socketName,
ZygoteServer zygoteServer) {
/* Hardcoded command line to start the system server */
String args[] = {
...
"--nice-name=system_server", // 指定进程名字 system_server
"--runtime-args",
"com.android.server.SystemServer", // 指定进程fork后要执行的程序
};
ZygoteConnection.Arguments parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
// 从zygote进程fork system_server进程
int pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
return true;
}
这段代码中指定了 fork 新进程的名称为system_server
,当进程被 fork 后会调用com.android.server.SystemServer#main()
方法。
先简单的看一下 fork 新进程的方法:
/**
* Fork system_server进程,并返回该进程的pid
*/
public static int forkSystemServer(int uid, int gid, ...) {
VM_HOOKS.preFork();
//
int pid = nativeForkSystemServer(uid, gid, ...);
VM_HOOKS.postForkCommon();
return pid;
}
native private static int nativeForkSystemServer(int uid, int gid, ...);
上述代码也比较清晰明了,实际上是调用了native
方法 fork 了一个新的进程。
接着会执行com.android.server.SystemServer#main()
方法,我们看一下该方法:
public final class SystemServer {
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
mFactoryTestMode = FactoryTest.getMode();
mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
private void run() {
...
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Within the system server, any incoming Bundles should be defused
// to avoid throwing BadParcelableException.
BaseBundle.setShouldDefuse(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Increase the number of binder threads in system_server
BinderInternal.setMaxThreads(sMaxBinderThreads);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
// 准备MainLooper
Looper.prepareMainLooper();
// 初始化家在系统的native服务组件
System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// 初始化系统Context
createSystemContext();
// 创建系统服务管理器,这个很关键
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
// 启动一些系统核心服务,很关键
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
...
// 让MainLooper无限循环的运行下去
Looper.loop();
hrow new RuntimeException("Main thread loop unexpectedly exited");
}
}
看到这一段代码时我们可能会有一种在黑暗中走了很久,终于看到阳光的感觉,我们看到main()
方法中实例化了SystemServer
,并调用该对象的run()
方法,然后开始初始化system_server
进程,该方法主要做了以下几件事:
Looper#prepareMainLooper()
准备 Android 主线程Looper
System#loadLibrary()
初始化native
环境createSystemContext()
创建应用上下文SystemServiceManager
以备后续启动系统中的其他核心服务startServices()
启动相关核心服务Looper#loop()
让主线程的Looper
跑起来这里的
Looper#loop()
和上文中platform/system/core/init.cpp
保活init
进程的原理相同,都是使用 Linux 的epoll
原理,关于Looper
的更多知识点请参阅这篇文章:
https://yanzhenjie.blog.csdn.net/article/details/89218745
接下来看一个超级简单又复杂的方法,创建系统上下文:
private Context mSystemContext;
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
有些同学觉得 Android 的Context
有点飘,但是想象 Java 这个面向对象语言,我们猜测它应该也是个普通对象吧,那么从这里更加证明了其实它也就是个普通的类,是个普通的对象而,只是它的能力可能比较多,不同的应用进程有不同的 Context 对象,通过 Context 可以获取该进程中应用的相关信息,然后我们再针对性的学习它在不同的情景下的能力就可以了。
在SystemServer#run()
方法中有以下几个非常重要的方法调用:
startBootstrapServices();
startCoreServices();
startOtherServices();
我们依次观察这三个方法的源代码,首先是startBootstrapServices()
,名字取得非常一目了然,望文生义,该访问是启动引导服务的,我们来看看启动了哪些服务:
/**
* Starts the small tangle of critical services that are needed to get
* the system off the ground. These services have complex mutual dependencies
* which is why we initialize them all in one place here. Unless your service
* is also entwined in these dependencies, it should be initialized in one of
* the other functions.
*/
private void startBootstrapServices() {
...
Installer installer = mSystemServiceManager.startService(Installer.class);
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
// 启动AMS,Acitivity管理服务
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
// 启动电源管理服务
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
mActivityManagerService.initPowerManagement();
mSystemServiceManager.startService(LightsService.class);
// 启动显示管理服务
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
...
// 启动包管理服务
mPackageManagerService = PackageManagerService.main(mSystemContext,
installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
// 启动用户管理服务
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
// 初始化缓存包中资源属性
AttributeCache.init(mSystemContext);
// 为系统进程设置Application实例
mActivityManagerService.setSystemProcess();
...
}
这段代码启动很多系统中的关键服务,如果深扒还有很多有趣的东西。这里比较有趣的是最后一句,我们可以简单的拿出一两句来瞅瞅,打开com.android.server.am.ActivityManagerServer#setSystemProcess()
:
public void setSystemProcess() {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this));
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
ApplicationInfo info = mContext.getPackageManager()
.getApplicationInfo("android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
...
}
看到第一句我们可能想起,我们获取ActivityManager
的方式:
ActivityManager am = Context.getSystemService(Context.ACTIVITY_SERVICE);
没错,它们是息息相关的东西,后面我会发布专门的文章来分析这个。
startCoreServices()
方法和startOtherServices()
方法也是启动一些核心服务,例如:
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;
我们在这里不深究了,我自己是把这块代码都看了一遍,建议读者也认真的阅读一遍,对我们的启发很大。
目光回到ZygoteInit#main()
中,我回顾下该方法最后的几句代码:
// 这里一定是true,启动SystemServer
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
// 运行zygote进程的select循环
zygoteServer.runSelectLoop(abiList);
...
可以看到,在成功的创建LocalServerSocket
对象后,就执行了zygote
进程的select
循环,该方法还是在ZygoteServer.java
中:
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws Zygote.MethodAndArgsCaller in a child process when a main()
* should be executed.
*/
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
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) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
这里就是不停的从LocalServerSocket
接受新连接,并且从一个spawn-request
的连接中一次性读取读取命令行调用ZygoteConnection#runOne(Ser)
。其实就是等待 AMS 来连接这个 Socket,以便启动新的进程来处理后续的事情。
直到这里,zygote
进程的启动和初始化就全部执行完毕,然后等待其他进程的请求再做其他的事,这里面错综复杂的地方很多,在本文中我们没有去深究,其实每一个分支我们都可以单独写一篇甚至几篇文章来分析。
最后我们对整个流程做个梳理:
系统启动时执行init
进程,init
的程序准备工作做完后会fork
一个名为zygote
的进程
platform/system/core/init/init.cpp
epoll
机制,使init
进程持续运行init.zygote.rc
配置文件指令告诉init
进程执行/system/bin/app_process
程序
platform/framework/base/cmds/app_process/app_main.cpp
根据init.zygote.rc
的指令参数,app_process
最终反射调用了com.android.internal.os.ZygoteInit#main()
Java 方法,该方法用来初始化zygote
进程
/dev/socket
目录下创建一个名为zygote
的 Socket 资源ZygoteInit#starSystemServer()
方法启动system_server
进程ZygoteInit#runSelectLoop()
方法循环接受客户端 Socket 连接请求,使zygote
进程持续运行ZygoteInit#main()
调用ZygoteInit#startSystemServer()
调用Zygote#forkSystemServer()
创建system_server
进程,并指定该进程执行com.android.sever.SystemServer#main()
方法
SystemServer#main()
方法初始化system_server
进程,其中主要做了以下几件事
system_server
进程的 Context(System Context)Looper#prepareMainLooper()
准备 MainLooperLooper#loop()
让 MainLooper 无限循环运行,使system_server
进程持续运行
Looper#loop()
方法中调用的是MessageQueue#next()
,该方法中使用死循环 + Linuxepoll
机制持续运行程序
最终zygote
执行句柄在ZygoteServer#runSelectLoop()
中无限循环运行,使zygote
进程持续运行
此时,系统启动完成,当我们需要启动一个 Android AMS 会通过 Socket 进程进行 IPC 通信,通知zygote
进程为这个应用程序创建一个新的进程。
本文到此结束,告辞!
版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com