Android设备的启动必须经历3个阶段,即BootLoader、Linux kernel和Android系统服务,默认情况下他们都有各自的启动界面。
第一个系统进程init
严格意义上来说,Android系统实际上是运行于Linux内核之上的一系列“服务进程”,并不算是一个完整意义上的“操作系统”。这些进程是维持设备正常工作的关键,而他们的老祖宗就是init
作为Android中第一个被启动的进程,init的PID值为0。它通过解析init.rc脚本来构建出系统的初始运行形态——其他Android系统服务程序大多是在这个“rc”脚本中描述并被相继启动的。Init.rc不但语法相对简单,而且因为采用了纯文本的编写方式,所以可读性很高,是开发商控制Android系统启动状态的一大利器。
关于init.rc的语法可以参考官方文档,一个完整的init.rc脚本由4种类型的生命组成,即:
-
Action(动作)
动作一般格式如下:
on <trigger> #触发条件 <command> ##执行命令 <command> #执行多个命令
从源码实现的角度来说,当相应的事件发生后,系统会对init.rc中的各进行匹配——只要发现符合条件的Action,就会把它加入“命令执行队列”的尾部(除非这个Action在队列中已经存在),然后系统再对这些命令按顺序执行。
常见事件
trigger Description boot 这是init程序启动后触发的第一个事件 <name> = <value> 当属性满足特定时触发。后面有关于属性的进一步介绍 device-added < path> device-removed 当设备节点添加/删除时触发此事件 service-exited 当指定的服务存在时触发 -
Commands
命令在所属事件发生时被一个个地执行
-
Services
Services其实是可执行程序,他们在特定的约束下会被init程序运行或者重启,他的一般格式为:
serice <name><pathname> [<argument>]* <option> <option>
name表示service的名称。pathname表示service的所在路径。argument为参数,option为service的约束选项
-
Options
Services中的可用选项
option Description critical 表明这是对设备至关重要的一个服务。如果他在四分钟内退出超过四次,则设备将重启进入恢复模式 disabled 此服务不会自动启动,而是需要通过显式调用服务名来启动 setenv <name><value> 设置环境变量为某个值
综合以上的分析就会发现,其实init.rc的语法可以用一个统一的形式来理解。如下所示
On <SOMETHING-HAPPEND>
<WHAT-TO-DO>
对于Action来说,他是当发生时去执行命令;而对于Service来说,他是always发生的(不需要启动触发条件),然后去启动指定的可执行文件(并且由Option来限制执行条件)。
根据文档中描述,会有下面四个事件依次被触发:
Init uses the following sequence of triggers during early boot. These are the built-in triggers defined in init.cpp.
early-init
- The first in the sequence, triggered after cgroups has been configured but before ueventd’s coldboot is complete.init
- Triggered after coldboot is complete.charger
- Triggered ifro.bootmode == "charger"
.late-init
- Triggered ifro.bootmode != "charger"
, or via healthd triggering a boot from charging mode.
系统关键服务启动简析
作为Android系统的第一个进程,init将通过解析init.rc来陆续启动其他关键的系统服务进程——其中最重要的就是ServiceManager、Zygote和SystemServer
Android中的“DNS”服务器——ServiceManager
Binder机制的“DNS服务器”负责域名(某Binder服务在Service Manager注册时提供的名称)到IP地址(由底层Binder驱动分配的值)的解析。ServiceManager是在Init.rc里描述并由init进程启动的。
//system/core/rootdir/init.rc
on init
...
# Start essential services.
start servicemanager
start hwservicemanager
start vndservicemanager
//frameworks/native/cmds/servicemanager/servicemanager.rc
service servicemanager /system/bin/servicemanager
class core animation
user system
group system readproc
critical
onrestart restart apexd
onrestart restart audioserver
onrestart restart gatekeeperd
onrestart class_restart --only-enabled main
onrestart class_restart --only-enabled hal
onrestart class_restart --only-enabled early_hal
task_profiles ServiceCapacityLow
shutdown critical
可以看到,servicemanager是一个linux程序,他在设备中的存储路径是/system/bin/service-manager。ServiceManager所属class是core,当ServiceManager每次重启时,其他关键进程如apexd、audioserver、gatekeeperd等也会被restart。
孕育新的线程和进程——Zygote
Zygote这个词的字面意思是“受精卵”,因而可以孕育出一个“新生命”,正如其名,Android中大多数应用进程或系统进程都是通过Zygote来生成的。和ServiceManager类似,Zygote也是由init解析rc脚本时启动的。
//system/core/rootdir/init.rc
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote
start zygote_secondary
//system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart media.tuner
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
从上面的脚本描述中可以看到,启动zygote要执行app_process64,并传入参数-Xzygote /system/bin --zygote --start-system-server
,下面分析一下app_process的主函数实现
//frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
// Parse runtime arguments. Stop at first unrecognized option.
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 (startSystemServer) {
args.add(String8("start-system-server"));
}
...
if (zygote) {
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.");
}
}
该函数解析启动app_process时传入的参数,对于启动zygote的情况来说,所有的参数都会作为它主函数的参数使用,如上面代码的args,在我们这个场景中,init.rc制定了–zygote选项,因而app_process接下来启动“ZygoteInit”并传入“start-system-server",之后ZygoteInit会运行于Java虚拟机上。runtime这个变量实际上是一个AndroidRuntime对象,其start函数源码如下:
//frameworks/base/core/jni/AndroidRuntime.cpp
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
}
VM启动后,会进入ZygoteInit类的main
函数中执行
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/**
* This is the entry point for a Zygote process. It creates the Zygote server, loads resources,
* and handles other tasks related to preparing the process for forking into applications.
*
* This process is started with a nice value of -20 (highest priority). All paths that flow
* into new processes are required to either set the priority to the default value or terminate
* before executing any non-system code. The native side of this occurs in SpecializeCommon,
* while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
* ZygoteConnection.handleChildProc, and Zygote.childMain.
*
* @param argv Command line arguments used to specify the Zygote's configuration.
*/
@UnsupportedAppUsage
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
...
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
if (!isRuntimeRestarted) {
if (isPrimaryZygote) {
FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
startTime);
} else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
startTime);
}
}
...
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
...
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
主要完成以下两个工作:
-
注册一个Socket:
new ZygoteSever()
Zygote是“孵化器”,一旦有新程序需要运行时,系统会通过这个Socket第一时间通知“总管家”,并由他负责实际的进程孵化过程
` -
启动systemServer:
forkSystemServer
如果app_process的调用参数中带有“—start-system-server”,那么此时就会通过
forkSystemServer
来启动SystemServer,
Zygote在前期主要担任启动系统服务的工作,后面有担当“程序孵化”的重任,为了协调好这两个工作的关系,通过forkSystemSever
创建新的进程来承载系统服务的运行,而后app_process所在的进程转变为Zygote的“孵化器”守护进程。
/**
* Prepare the arguments and forks for the system server process.
*
* @return A {@code Runnable} that provides an entrypoint into system_server code in the child
* process; {@code null} in the parent.
*/
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
/* 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,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs;
int pid;
try {
ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
try {
parsedArgs = ZygoteArguments.getInstance(commandBuffer);
} catch (EOFException e) {
throw new AssertionError("Unexpected argument error for forking system server", e);
}
commandBuffer.close();
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
...
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
ZygoteInit.forkSystemServer
调用Zygote.forkSystemServer
函数,该函数内部利用UNIX的fork机制创建出了一个新进程;而这个“新生儿”(即pid==0分支)会在随后的执行过程中通过handleSystemServerProcess
来启动各种支撑系统运行的System Server。在跟踪SystemServer的具体启动过程之前,我们先来为Zygote接下来的工作做一个分析,与我们之前所见得fork处理流程不同的是,startSystemSever
中并没有为父进程专门开辟一个代码分支,因而父进程在ZygoteInit.forkSystemServer
后会回到ZygoteInit
的主函数中(java虚拟机),执行后面的
// The select loop returns early in the child process after a fork and loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
这是一个死循环——除非Zygote退出或者出现异常才会跳出循环。
/**
* 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.
* @param abiList list of ABIs supported by this zygote.
*/
Runnable runSelectLoop(String abiList) {
...
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
if (mUsapPoolEnabled) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = mUsapPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
// The usapPipeFDs array will always be filled in if the USAP Pool is enabled.
assert usapPipeFDs != null;
for (int usapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
}
...
int pollReturnValue;
try {
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
// The poll returned zero results either when the timeout value has been exceeded
// or when a non-blocking poll is issued and no FDs are ready. In either case it
// is time to refill the pool. This will result in a duplicate assignment when
// the non-blocking poll returns zero results, but it avoids an additional
// conditional in the else branch.
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else {
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
final Runnable command =
connection.processCommand(this, multipleForksOK);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
// We're in the child. We should always have a command to run at
// this stage if processCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processCommand. This
// shows up as a regular POLLIN event in our regular processing
// loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
}
...
}
...
}
}
从程序中可以看到runSelectLoop
的主体就是while死循环,它将作为zygote的守护体存在,重点在于当zygote的socket收到来自客户端的连接时,产生新的connection,然后执行processCommand
函数进行处理。
final Runnable command = connection.processCommand(this, multipleForksOK);
/**
* Reads a command from the command socket. If a child is successfully forked, a
* {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
* process. {@code null} is always returned in the parent process (the zygote).
* If multipleOK is set, we may keep processing additional fork commands before returning.
*
* If the client closes the socket, an {@code EOF} condition is set, which callers can test
* for by calling {@code ZygoteConnection.isClosedByPeer}.
*/
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
...
if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
// Continue using old code for now. TODO: Handle these cases in the other path.
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
...
}
该函数调用forkAndSpecialize
来创建承载应用程序的新进程。Specialize的字面意思是专门化,表达了forkAndSpecialize
在“孵化”的同时也把它转变为Android应用程序的目标,函数forkAndSpceialize
的处理也分为三个阶段,即
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
bindMountAppStorageDirs);
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
// If no GIDs were specified, don't make any permissions changes based on groups.
if (gids != null && gids.length > 0) {
NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
}
}
// Set the Java Language thread priority to the default value for new apps.
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
- prefork
- nativeForkAndSpecialize
- postForkCommon
我们主要关心nativeForkAndSpecialize,这是个native方法,对应着下面的函数
//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags,
jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
...
pid_t pid = zygote::ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore, true);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
mount_storage_dirs == JNI_TRUE);
}
return pid;
}
// Utility routine to fork a process from the zygote.
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
const std::vector<int>& fds_to_close,
const std::vector<int>& fds_to_ignore,
bool is_priority_fork,
bool purge) {
...
pid_t pid = fork();
if (pid == 0) {
if (is_priority_fork) {
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
} else {
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
}
...
} else {
ALOGD("Forked child process %d", pid);
}
}
ForkCommon
函数中调用了fork
函数,并将子进程的优先级设置为MAX,再回到com_android_internal_os_Zygote_nativeForkAndSpecialize
中执行SpecializeCommon
,该函数中设置子进程的私有数据,如调度策略、uid等,最后再将自己的优先级恢复正常。之后回到processCommand
中,父进程进行一些扫尾工作,包括:将子进程加入进程组;正确关闭文件;调用方法返回结果值等,子进程调用handleChildProc
来执行目标进程的入口函数
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
/*
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
closeSocket();
Zygote.setAppProcessName(parsedArgs, TAG);
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) {
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.mRemainingArgs);
// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(
parsedArgs.mRemainingArgs /* classLoader */);
}
}
}
该函数会调用ZygoteInit.zygoteInit
,zygoteInit
调用 RuntimeInit.applicationInit
,最后通过
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
执行startClass类的main函数,那么这个startClass具体是什么呢?要回答这个问题并不是件容易的事情,需要大家对应用程序的启动流程有一个全局的认识,我们假设当前的流程已经到了ActivityManagerService,他会想Zygote发起一个创建进程的请求。
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
最终层层向下会调用
//frameworks/base/services/core/java/com/android/server/am/ProcessList.java
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks, String abiOverride) {
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
}
//最终调用下面的函数
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
...
final Process.ProcessStartResult startResult;
boolean regularZygote = false;
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
app.getDisabledCompatChanges(),
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else {
regularZygote = true;
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
}
}
可以看到其中有一段代码为final String entryPoint = "android.app.ActivityThread";
因此可以认为Zygote中执行的是ActivityThread类的main函数,这同时也是我们熟知的Android应用程序的主线程。
//frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
到目前为止我们总结一下,app_process64一开始申请socket,然后fork出子进程执行SystemServer,父进程执行死循环监听socket,如果socket中有来自客户端的消息,则fork出进程,并执行ActivityThread的main函数。
SystemServer
从前面的分析可以知道,ZygoteInit.forkSystemServer调用Zygote.forkSystemServer来创建子进程,然后在pid==0的分支中调用handleSystemServerProcess,
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
...
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
handleSystemServerProcess
同样会调用ZygoteInit.zygoteInit
,zygoteInit
调用 RuntimeInit.applicationInit
,但和执行普通进程的目标函数不同,此时的systemserver的startClass已经换成了forkSystemServer
时args数组中的com.android.server.SystemServer
。
String[] args = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011,3012",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
因此最终applicationInit
将调用SystemServer的main
函数。之后SystemServer开始执行,启动各种系统服务,启动过程不再赘述。其中最值得我们关心的时ActivityManagerService,我们放到下次再讲。