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 客户端的请求
init.rc 配置文件的作用和运行流程
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.zygote.rc 配置文件的含义和作用
打开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文件中,接下来我们详细分析该文件。
ZygoteInit.java 初始化 zygote 进程的过程
上面讲到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 方法
反射调用 Java 类com.android.internal.os.ZygoteInit#main()方法,并把 fork zygote进程时的参数传入用来辅助初始化zygote进程
此时,我们回到启动zygote进程的地方回顾一下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
1
根据上述分析,此时调用句柄已经执行到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()创建 Java 层的 ServerSocket 对象
上面说到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 <socket.h>
/*
* 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<name> ("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"
1
2
如果你手里有个 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 对象。
ZygoteInit.java 启动 system_server 进程的过程
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 了一个新的进程。
SystemServer.java 初始化 system_server 进程的过程
接着会执行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进程,该方法主要做了以下几件事:
一些有关系统的初始化工作,例如 VM 虚拟机、运行时环境和线程池优先级等
调用Looper#prepareMainLooper()准备 Android 主线程Looper
调用System#loadLibrary()初始化native环境
调用createSystemContext()创建应用上下文
实例化SystemServiceManager以备后续启动系统中的其他核心服务
调用start<Name>Services()启动相关核心服务
调用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);
1
没错,它们是息息相关的东西,后面我会发布专门的文章来分析这个。
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;
我们在这里不深究了,我自己是把这块代码都看了一遍,建议读者也认真的阅读一遍,对我们的启发很大。
zygote 进程等待 Socket 客户端的请求
目光回到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
使用死循环 + Linuxepoll机制,使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)
启动 AMS 和 WMS 等系统核心服务
调用Looper#prepareMainLooper()准备 MainLooper
调用Looper#loop()让 MainLooper 无限循环运行,使system_server进程持续运行
Looper#loop()方法中调用的是MessageQueue#next(),该方法中使用死循环 + Linuxepoll机制持续运行程序
最终zygote执行句柄在ZygoteServer#runSelectLoop()中无限循环运行,使zygote进程持续运行
此时,系统启动完成,当我们需要启动一个 Android AMS 会通过 Socket 进程进行 IPC 通信,通知zygote进程为这个应用程序创建一个新的进程。