安卓架构图
loader>kernel>native>framework>app
作为安卓的第一个进程init(pid =1),init将通过解析init.rc来陆续启动其他关键服务进程(ServiceManager,Zygote和SystemServer)
如果你本地看不了源码的话,可以通过在线查看源码(https://www.androidos.net.cn/android/5.1.0_r3/xref/system/core/rootdir/init.rc)
/system/core/rootdir/init.rc
healthd 电池服务进程
zygote 卵进程
media 多媒体进程
surfaceflinger suface进程
drm Digital Rights Managemen,也就是数字版权加密保护技术。
servicemanager 是一个Linux 程序。它在设备中的存储路径是 /system/bin/servicemanager/ 所属的class 为core 根据该特性,这些进程会同时被启动或停止。cirtical 表示的是系统的关键进程-意味着如果进程不幸在4分钟内异常退出超出4次,这设备将重启并进入还原模式。当servicemanager 每次重启时,其他关键进程如Zygote,media,surfaceflinger等也会被restart。
zygote 卵进程
卵进程干什么用的?
其实Android中大部分的进程和系统进程都是通过Zygote 来生成的
接下来分析一下Zygote是如何启动的
其实跟servicemanager一样也是通过init进程解析init.rc脚本启动的。早期版本android中的Zygote的启动命令是在init.rc中,但是随着硬件的不断升级换代,Android系统不得不面对32位和64位机器同时存在的情况,因而对Zygote的启动也需要根据不同的情况区分对待。
一般会有不同的Zygote的脚本,比如
现以init.zygote64.rc为例查看一下相关代码
从上面可以看出
servicename 为zygote
path:/system/bin/app_process64
属性-Xzygote /system/bin --zygote --start-system-server
Zygote 所属于的class 为main 而不是core
从路径上来看他所在的进程名叫app_process64 而不像servicemanager 一样在一个独立的进程中。通过指定的--zygote参数,app_process可以识别用户是否需要启动zygote,接下来看一下这个app_process到底是什么?
先看一下Android.mk文件
上述是构建32位和64位系统的一个编译脚本。其中LOCAL_MULTILTB 表示同时编译32位和64位
接下来分析一下app_process的主函数就知道其内部逻辑
int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
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
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) { //是否需要启动system server
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 (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
这个函数用于解析app_process 时传入的参数,具体如下
--zygote: 表示当前进程用于承载zygote
--start-system-server:是否需要启动system server
--application: 启动进入独立的程序模式
--nice-name: 此进程的“别名”
对于非zygote的情况下,在上述参数的末尾会跟上main class 的名称,而后的其他参数则属于这个class 的主函数入参;对于zygote的情况,所有参数则会作为它的主函数入参使用。
init.rc指定了--zygote选项,因而app_process 接下来将启动"ZygoteInit“”并传入“start-system-server”,之后ZygoteInit会运行与java虚拟机上,为什么?
原因就是runtime这个变量实际是一个AndroidRuntime对象,其start函数源码如下
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
if (startVm(&mJavaVM, &env) != 0) { //启动虚拟机
return;
}
onVmCreated(env); //虚拟机启动后的回调
...
}
当虚拟机成功启动,并进入ZygoteInit的执行中:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start(); boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true; //需要启动Sytem server
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
} if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}registerZygoteSocket(socketName); //注册一个Socket
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(); //预加载各类资源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis()); // Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup
gc(); //执行gc操作 // Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false); if (startSystemServer) {
startSystemServer(abiList, socketName);
} Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList); closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
Zygote主要完成两项工作
注册一个Socket
Zygote是”孵化器”,一旦有新程序需要运行时,系统会通过这个Socket(完整的名称为ANDROID_SOCKET_zygote)在第一时间通知“总管家”,并由它负责实际的进程孵化过程。
预加载各类资源
函数preload用于加载虚拟机运行时所需的各类资源,包括:
preloadClassed(); //负责加载和初始化常用的一些classed
preloadResources();//负责加载和初始化常用的一些资源文件
preloadOpenGL();//负责加载和初始化OpenGL
preloadSharedLibraries();//负责加载和初始化共享库
启动System Server
如果app_process的调用参数中带有“--start-system-server”,那么此时就会通过startSystemServer来启动System Server.
Zygote前期主要担任启动系统服务的工作,后期则又担当"程序孵化”的重任。但是Zygote只在init.rc中被启动一次,它是如何协调好这两项工作的关系呢?我们可以推断一下,上述的startSystemServer应该会新建一个专门的进程来承载系统服务的运行,而后app_process 所在的进程则转变为Zygote的“孵化器”守护进程。那么是不是这样子呢?
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
上述代码段出现了我们熟悉的fork流程-forkSystemServer 在内部利用UNIX的fork机制创建了一个新的进程;而这个“新生儿”(即 pid ==0 分支)会在随后的执行过程中通过handleSystemServerProcess来启动各个支撑系统运行的System Server。
在跟踪System Server 的具体启动过程之前,我们先来为Zygote接下来的工作做一个分析,startSystemServer中并没有为父进程专门开辟一个代码分支。因而这个函数最后会通过return ture 而返回到Zygoteinit 的主函数中。紧随其后的语就是
runSelectLoop(abiList);
查看源码:
static final int GC_LOOP_COUNT = 10;
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
sServerSocket.getFileDescriptor());
peers.add(null); //添加null是为了保持fds 和peers的一致性
int loopCount = GC_LOOP_COUNT; 设定多少次循环才调用垃圾回收函数gc(),
while (true) { //确实是死循环
int index;
if (loopCount <= 0) {
gc(); //gc操作
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
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(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else { //已建立的连接中有客户端发过来的数据需要处理
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
从程序中可以看到,runSelectLoop的主体的确是一个while死循环,它将作为zygote的守护体存在,因为zygote此时运行在虚拟机环境中,所以它需要考虑垃圾回收的问题。不过这是一项非常耗时的操作,如果操作频繁,每次收回的垃圾并不会很多,那么就得不偿失。所以上述函数中设定了GC_LOOP_COUNT 为10,意味着while每循环十次才会调用一次gc()。那么while执行一轮都完成了那些工作呢?
我们从sServerSocket.getFileDescriptor() 获取到的是前面通过registerZygoteSocket 创建的Server Socket的文件描述符,它会被添加到一个ArrayList<FileDescriptor> 类型的fds变量中。这同时也意味着zygote中不光只有一个socket产生。具体而言,while循环中会先通过如下两个语句来判断当前哪个fd处于可读状态
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
当fds这个ArrayList指示的某个文件有可读数据时,返回的index值就代表此文件对应的file descriptor在队列中的序列。另外,这个函数还有一个特殊的返回值:0.。因为fds中的第一个元素为Zygote的Server Socket,所以index为0代表了有新的连接请求。这和网络连接中的Socket概念是一致的。
index = 0
此时我们需要通过acceptCommandPeer 来接受来自客户端的连接,产生一个新的ZygoteConnection,然后分别更新peers 和fds.为了保证这两个列表中的对象序列号保持一致,可以看到peers在初始化时专门添加了一个null,对应的是Zygote Server Socket这个“监听者”
index > 0
此时说明已经建立的Socket连接中有来自客户端的数据需要处理,完成具体的工作的是runOnce,下面我们详细分析一下这个函数:
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
...
try {
checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
logAndPrintError(newStderr, "Invalid zygote arguments", ex);
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
}
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serQverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
有两点需要重点注意:
创建承载应用程序的新进程
这是在意料之中的,zygote需要为每个新启动的应用程序生成自己独立的进程。不过runOnce中并没有直接使用fork来完成这一工作,而是调用了forkAndSpecialize,稍后会分析这个函数的实现。另外,新的创建的进程中一定需要运行应用程序本身的代码,这一部分工作是在handlerChildProc中展开的。
父进程的“扫尾”工作
执行完上述的任务之后,父进程还需要做一些清尾的工作才算“大功告成”。包括:将子进程加入进程组;正确关闭文件;调用返回结果值等。
Specialize的字面意思是“专门化”,表达了forkAndSpecialize在“孵化”的同时也把它转变为Android应用程序的目标。函数forkAndSpecialize的处理分为3个阶段,即preFork,nativeForkAndSpecialize 以及postForkCommon.
/frameworks/base/core/java/com/android/internal/os/Zygote.java
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
接下来直接分析preFork在Zygote中对应的实现
/art/runtime/native/dalvik_system_ZygoteHooks.cc
static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
Runtime* runtime = Runtime::Current();
CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
runtime->PreZygoteFork();
// Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
Thread* self = Thread::Current();
return reinterpret_cast<jlong>(self);
}
这里的Runtime实例具体而言指的是Zygote进程中的运行环境, runtime->PreZygoteFork()又会间接的调用Headp::PreZygoteFork,从而完全堆空间的初始操作。
函数nativeForkAndSpecialize 是一个native方法,具体对应的实现是com_android_internal_os_Zygote_nativeForkAndSpecialize ,后者则又进一步调用了ForkAndSpecializeCommon;
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jstring instructionSet, jstring dataDir) {
uint64_t start = MsTime();
SetSigChldHandler();
ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
pid_t pid = fork(); //这里才是真正孵化出一个新进程
if (pid == 0) {//子进程中
...
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server ? NULL : instructionSet);
ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
...
} else if (pid > 0) {
// the parent process 这里什么也不做因为父进程有处理
}
return pid;
}
}
这个函数首先会fork一个新进程,并在pid == 0这一分支中为孵化的进程完成一系列初始化操作,而后执行CallStaticVoidMethod.其中gZygoteClass对应的是“com/android/internal/os/Zygote”,而gPostForkChildHooks则是Zygote这个类中的成员变量函数callPostForkChildHooks --从名称可以看出用于执行孵化后的一些处理工作。ForkAndSpecializeCommon也还没有设计与应用程序相关的具体业务,这部分工作会由runOnce中的handleChildProc 来完成,核心代码如下:
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
...
if (parsedArgs.niceName != null) {//子进程的别名
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.runtimeInit) {
...
} else {//应用程序的ActivityThread将在这里执行
String className;
try {
className = parsedArgs.remainingArgs[0];
} catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument", null);
return;
}
String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
System.arraycopy(parsedArgs.remainingArgs, 1,
mainArgs, 0, mainArgs.length); //className 主函数参数
if (parsedArgs.invokeWith != null) { //invokeWith的情况
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
} else {
ClassLoader cloader;
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
} else {
cloader = ClassLoader.getSystemClassLoader();
}
try { //执行main函数
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
}
}
这个函数的任务用一句话来概括,就是找到并执行目标进程的入口函数。Android系统中所有的应用程序理论上都是由Zygote启动的;而且我们不难发现Zygote会为新启动的应用fork一个进程。不过和传统的内核中的fork+exec的做法不同的地方是,Zygote中并不会执行exec().。这在某些情况下就会造成一些障碍,比如无法使用valgrind来检测程序的内存泄漏情况。为了响应开发人员的类似需求,Android系统特别提供了一种Wrapper实现,并通过parsedArgs.invokeWith来加以控制
在handleChildProc这个函数中,最重要的参数之一是className。可以看到,handleChildProc会把className对应的类加载到内存中,然后执行其中的main函数。那么这个className具体指的是什么呢?
其实是后续ActivityManagerServer,它会向Zygote发起的一个创建新进程的请求,代码如下
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);//这些参数将被转化为Arguments中的成员变量
...
}
Process的字面意思虽然是进程,但其实它属于“进程类”,或者成为“进程管家”会贴切些。Process.jar显然是去启动一个新的进程来继承业务,而函数的第一个参数entryPoint,即我们在handleChildProc中看到的className。这是因为ActivityManagerService传递过来的字符串形式列表会被Arguments.paseArgs解析成Arguments中的各个成员变量,
各成员变量
参数格式 | 对应的成员变量 |
“--setuid=” | uid |
"--setgid=" | gid |
"--target--sdk-version=" | targetSdkVersion |
"--runtime-init" | runtimeInit |
"-classpath" | classPath |
"--nice-name=" | nicename |
剩余的参数 | remainingArgs |
现在问题转化为,ActivityManagerService 中的entryPoint是如何得来的呢?它的来源简单来讲就是下面的这个语句。
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
换句话说,Zygote中主动执行的类是ActivityThread,这同时也是我们熟知的Acitivity应用程序的“主线程”:
/frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
到目前为止,我们已经分析了Zygote作为守护进程时,如何为Android应用程序的启动而服务的。接下来要了解引导系统各个重要服务的启动过程。
从前面可以知道,System Server的启动是在startSystemServer中完成的。Zygote首先会利用Zygote.forkSystemServer来孵化处一个子进程,然后在pid==0的分支中调用handleSystemServerProcess,后者在函数的末尾又会进一步调用RuntimeInit.zygoteInit:
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}
函数zygoteInit通过3个方面来完成初始化,分别是:
commonInit
通用部分的初始化,包括设置默认的uncaught exeception handler;为HttpURLConnection准备好默认的Http User_Agent;开启trace模式(只在emulator下才有必要)等。
nativeZygoteInit
这是一个本地初始化函数,也是zygoteInit中的重点,我们稍后会做重点分析。
applicationInit
这个函数的声明为:private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader);从中可以看出它是程序运行的“起点”。在我们这个场景中,程序指的是SystemServers,而"入口"是什么呢?这就和第二个参数argv有关系.。这个Sting[]实际上包含了两个重要的成员变量,即startClass 和startArgs。而这两个变量的赋值可以追溯到startSystemServer中,具体代码如下:
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
换句话说,startClass 对应的就是com.android.server.SystemServer。因而applicationInit最终将调用main@SystemServer:
public static void main(String[] args){
new SystemServer().run();
}
经过上面的初始化后,程序现在会有两个分支,其一是nativeZygoteInit 主导的本地系统服务的启动:另一个则是applicationInit负责的java层系统服务的启动。
(1)本地系统服务的启动
在JNI机制中,Native函数在java层会有一个声明,然后在本地层得到真正的实现。那么当我们调用了java层的函数后,系统是如何找到Native中与之对应的函数的呢?通常情况下,Native中的C++文件名称是以java层的package为基础的,如java层的包名为com.android.internal.XX,那么其对应的JNI层文件则是com_android_internal_XX。不过这种对应关系并不是绝对不变的,可以根据开发人员的需求进行调整。譬如我们上面讲的ZygoteInit所在的java包是com.android.initernal,而实际上JNI的实现则为AndroidRuntime.cpp。
AndroidRuntime 表明这个class的任务是“负责Android的运行时环境”。当我们调用了nativeZygoteInit后,实际上是执行了 com_android_internal_os_RuntimeInit_nativeZygoteInit@AndroidRuntime.cpp,代码如下:
/frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
全局变量gCurRuntime是一个AndroidRuntime的对象,结合之前能想象到AndroidRuntime是一个父类,真正的实现则在App_main.cpp中的AppRuntime。当我们新建AppRuntime对象时,它的父类的构造函数会被调用,并为gCurRuntime赋值。上述的onZygoteInit也在这个App_main.cpp文件中,如下所示:
/frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
上面这段代码是Binder机制中的重要组成部分,其中startThreadPool将开启Binder线程池以保证其他进程可以正确访问到Zygote所提供的服务。Zyogte通过JNI和回调的方式非常巧妙地把本地层和java层,SystemServer和App process关联起来了。
(2)java层系统服务的启动
java层的系统服务比较多,它们各司其职,缺一不可。我们知道,Zygote会为System Server的运行启动和初始化虚拟机,并通过入口main@System.java 开启 “系统服务之旅”。不过main函数只起到“门”的作用,它又会直接调用SystemServer().run(),后者才是真正实现服务的地方:
private void run() {
try {
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
...
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper(); //准备主循环体
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
System.loadLibrary("android_servers"); //加载本地服务库
...
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
StrictMode.initVmDefaults(null);
// Loop forever.
Looper.loop(); //进入死循环,直到设备关机
throw new RuntimeException("Main thread loop unexpectedly exited");
}
System Server 在启动前首先需要做很多初始化设置,包括将VM的版本记录到系统变量中,设置线程优先级,设置堆的使用率等。我们知道,Android系统服务会被分为两类,其一就是java层的,其二就是本地层的。后者具体事由System.loadLibrary("android_servers")实现的
通过以上我们可以看到app_process就是系统服务的“根据地”。它在init进程的帮助下,通过Zygote逐步建立起各SystemServer的运行环境,继而为上层的“繁殖壮大”提供“土壤环境”。
流程图转自:()
全文借鉴《Android内核设计思想》
后续分析SystemServer以及ActivityManagerService