在分析Activity启动的文章《Android Activity启动过程分析》中,我们遗留了一个小尾巴——App冷启动的情况下,当时没有讲解进程创建的过程,现在我们就把这个尾巴接上,一起看看Android中App进程创建的过程(本文分析过程是基于Android Q源码)。
先给结论:在Android系统中创建App进程是由zygote进程负责创建的;在一个App种冷启动另一个App时,首先会经过system_server进程种的ActivityManagerSrevice生成创建进程的请求,创建进程的请求由system_server进程发给zygote进程的;system_server和zygote进程之间是通过socket(UNIX Domain Socket)进行通信的。
在了解上面逻辑后,我们先看下看下zygote socket是如何创建的。
zyoget socket创建是在解析init.zygote32.rc
(也可能是init.zygote64.rc、init.zygote32_64.rc等文件)后创建的,我们看下这个文件的内容:
//文件位置:system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -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 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
关于init.zygote32.rc文件的解析可参考《Android系统启动之Zygote》,这里就不再重复了。socket zygote stream 660 root system
和socket usap_pool_primary stream 660 root system
这两个命令被解析后会创建两个本地socket,分别对应Android设备的/dev/socket/zygote
、/dev/socket/usap_pool_primary
两个节点。Socket创建和绑定过程如下:
//system/init/descriptors.cpp
void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
// Create
const std::string& contextStr = context_.empty() ? globalContext : context_;
//创建Socket并返回文件描述符,Create()函数会调用system/init/util.cpp中的CreateSocket()函数
int fd = Create(contextStr);
if (fd < 0) return;
std::string publishedName = key() + name_;
LOG(INFO) << "CreateAndPublish publishedName: " << publishedName << "";
std::for_each(publishedName.begin(), publishedName.end(),
[] (char& c) { c = isalnum(c) ? c : '_'; });
std::string val = std::to_string(fd);
//将文件描述符保存在环境变量中。
setenv(publishedName.c_str(), val.c_str(), 1);
// make sure we don't close on exec
fcntl(fd, F_SETFD, 0);
}
DescriptorInfo::CreateAndPublish()
函数主要作用是创建socket和将socket节点的文件描述符存入环境变量中。我们看下CreateSocket()函数
//system/init/util.cpp
/*
* 在/dev/socket目录下创建unix domain socket
*/
int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid,
const char* socketcon) {
if (socketcon) {
if (setsockcreatecon(socketcon) == -1) {
PLOG(ERROR) << "setsockcreatecon(\"" << socketcon << "\") failed";
return -1;
}
}
//创建socket
android::base::unique_fd fd(socket(PF_UNIX, type, 0));
if (fd < 0) {
PLOG(ERROR) << "Failed to open socket '" << name << "'";
return -1;
}
if (socketcon) setsockcreatecon(NULL);
struct sockaddr_un addr;
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
name);
if ((unlink(addr.sun_path) != 0) && (errno != ENOENT)) {
PLOG(ERROR) << "Failed to unlink old socket '" << name << "'";
return -1;
}
std::string secontext;
if (SelabelLookupFileContext(addr.sun_path, S_IFSOCK, &secontext) && !secontext.empty()) {
setfscreatecon(secontext.c_str());
}
if (passcred) {
int on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
PLOG(ERROR) << "Failed to set SO_PASSCRED '" << name << "'";
return -1;
}
}
//绑定socket,为socket分配地址
int ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
int savederrno = errno;
if (!secontext.empty()) {
setfscreatecon(nullptr);
}
if (ret) {
errno = savederrno;
PLOG(ERROR) << "Failed to bind socket '" << name << "'";
goto out_unlink;
}
if (lchown(addr.sun_path, uid, gid)) {
PLOG(ERROR) << "Failed to lchown socket '" << addr.sun_path << "'";
goto out_unlink;
}
if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
PLOG(ERROR) << "Failed to fchmodat socket '" << addr.sun_path << "'";
goto out_unlink;
}
LOG(INFO) << "Created socket '" << addr.sun_path << "'"
<< ", mode " << std::oct << perm << std::dec
<< ", user " << uid
<< ", group " << gid;
return fd.release();
out_unlink:
unlink(addr.sun_path);
return -1;
}
CreateSocket()函数实现了创建socket节点并为其分配地址;至此Zygote socket就创建完成了。
在知道zygote socket是怎么创建后,我们看下zygote socket的服务端是怎么创建并监听的。
socket服务端是在ZygoteInit.main()方法中创建并初始化的,整个流程可参考上面的时序图;整个过程分为两步:一、创建LocalServerSocket,并监听/dev/socket/zygote
节点;二、进入一个死循环,等待客户端发送数据。我们先看下创建LocalServerSocket的过程:
//ZygoteServer.java
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
//isPrimaryZygote是在ZygoteInit.main()方法中传入的,
//如果没有init.zygote32.rc中没有通过`--socket-name=`指定socket名字,则该值为true.
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
fetchUsapPoolPolicyProps();
mUsapPoolSupported = true;
}
在ZygoteServer构造方法中主要是初始化mZygoteSocket、mUsapPoolSocket;我们看下createManagedSocketFromInitSocket()
方法的实现
//Zygote.java
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//从系统环境变量中获取socket的文件描述符,该描述符是在创建socket节点后写入了系统环境变量中;
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//创建LocalServerSocket对象,并返回该对象
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
注释中已经做了说明,我们继续看LocalServerSocket构造方法
//LocalServerSocket.java
public LocalServerSocket(FileDescriptor fd) throws IOException
{ //创建LocalSocketImpl对象,LocalSocketImpl为Socekt功能实现类;
impl = new LocalSocketImpl(fd);
//监听`/dev/socket/zygote`
impl.listen(LISTEN_BACKLOG);
localAddress = impl.getSockAddress();
}
上面就是服务端LocalServerSocket创建并监听/dev/socket/zygote
的过程,现在我们看下等待客户端连接和处理客户端命令的实现,这个实现是在ZygoteServer.runSelectLoop()方法中。
//ZygoteServer.java
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
int[] usapPipeFDs = null;
StructPollfd[] pollFDs = null;
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;
}
//省略部分代码.....
try {
//阻塞等待文件描述符上的POLLIN事件发生,最终是通过linux系统函数poll实现;
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// 和客户端建立连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
try {
ZygoteConnection connection = peers.get(pollIndex);
// 处理客户端发送过来的命令
final Runnable command = connection.processOneCommand(this);
// 如果创建了子进程,mIsForkChild为true,然后返回command命令
if (mIsForkChild) {
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
if (command != null) {
throw new IllegalStateException("command != null");
}
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
Slog.e(TAG, "Exception executing zygote command: ", e);
ZygoteConnection conn = peers.remove(pollIndex);
conn.closeSocket();
socketFDs.remove(pollIndex);
} else {
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
} finally {
mIsForkChild = false;
}
} else {
//省略部分代码.....
}
//省略部分代码.....
}
}
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
//mZygoteSocket.accept()最终会调用系统accept()函数,
//关于accept()函数可参考 https://man7.org/linux/man-pages/man2/accept.2.html
return createNewConnection(mZygoteSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
在这个方法中主要做了以下几件事:
前面两点已经在注释中说明,第三点我们稍后讲解,我们先看zygote socket客户端创建过程
在了解socket服务端的创建和监听过程后,你肯定会想,那客户端是怎么创建并和服务端建立连接的呢,现在我们就来了解下。在《Android系统启动之SystemServer(二)》中,我们知道在SystemServer启动过程中会创建一系列的系统服务,我们zygote socket 客户端也是在这个过程中创建并和服务端建立连接的。整个过程如下时序图所示:
在SystemServer.startOtherService()方法中会调用ZygoteProcess的preloadDefault()方法,在ZygoteProcess.attemptConnectionToPrimaryZygote()方法种会判断其成员变量primaryZygoteState对象(ZygoteState实例对象,ZygoteState是ZygoteProcess的私有静态内部类)是否为空和是否关闭,这实际上就是判断客户端和zygote socket服务端是否建立会话连接;如果没有建立连接或者连接已关闭则走后续的创建客户端socket并连接的过程。客户端socket为LocalSocket对象,服务端socket为LocalServerSocket,他们功能实现类都是LocaSocketImpl,最终也都借助Linux系统函数实现。整个客户端创建的过程比较简单,大家可以根据上面的时序图跟下代码。接下来,我们开始回到最初的问题,App进程是怎么创建的,有了前面的基础,我们再来看这个问题就比较简单了。
讲了大半天,终于回到了文章的主题——App进程创建过程,进程创建分为两个过程:
我们先看system_server发出创建进程命令的过程,在前一篇《Android Activity启动过程分析》文章中,讲到Activity启动过程中,如果Activity所在的进程没有创建,则会创建进程,我们还是以从Activity冷启动分析,看下应用进程创建过程是怎样的。回到Activity启动过程中调用ActivityStackSupervisor.startSpecificActivityLocked()方法。
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
//如果进程已创建,则继续启动Activity的流程,并return
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
knownToBeDead = true;
}
if (getKeyguardController().isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
//进程没有创建的情况,这个情况下会创建一个Message对象,
//该Message的Callback即为调用ActivityManagerInternal.startProcess()方法
//参数为mService.mAmInternal, r.processName, r.info.applicationInfo, knownToBeDead,
//"activity", r.intent.getComponent()
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
注释中已做了说明,整个过程如下时序图所示(图中省略了ProcessList.startProcessLocked()重载方法的调用):
最后创建进程的请求是由ZygoteProcess.attemptZygoteSendArgsAndGetResult()方法发出的,在讲Zygote Socket客户端 创建过程,我们知道ZygoteProcess的成员变量primaryZygoteState是zygote socket客户端和服务端通信的桥梁,它封装了输入输出流。所以最终的命令就是通过primaryZygoteState中的字符输出流发送给服务端的。我们看下具体流程,先从ActivityManagerService.startProcessLocked()方法开始
//ActivityManagerService.java
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
在ActivityManagerService.startProcessLocked()方法中会调用ProcessList类中的startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler)
,这个方法经过几个重载方法的调用最终会调用startProcess()方法
//ProcessList.java
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
//entryPoint值为"android.app.ActivityThread",赋值的地方是在
/**
*boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
* boolean disableHiddenApiChecks, boolean mountExtStorageFull,
* String abiOverride) {
* // 省略部分代码....
* final String entryPoint = "android.app.ActivityThread";
* return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
* runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
* startTime);
* // 省略部分代码....
*}
*/
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkSlow(startTime, "startProcess: asking zygote to start proc");
final Process.ProcessStartResult startResult;
//这里判断HostingRecord.mHostingZygote变量的值,该值用于描述用那种类型的Zygote创建新的进程
//这个值在HostingRecord的构造函数中赋值,在ActivityManagerSerice.LocalService.startProcess()方法中
//创建HostingRecord时,mHostingZygote为默认值HostingZygote.REGULAR_ZYGOTE,此时对应的是最后的else情况
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,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
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,
/*useUsapPool=*/ false,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
这个方法判断是通过什么方式启动发送启动进程的,实际上行最终都是会调用ZygoteProcess.start()方法;这个方法有一个比较重要的参数entryPoint
,这个决定了zygote进程创建进程后会调用哪个类的main()方法,关于这个参数的初始化已经注释中说明。接着start()方法会调用startViaZygote()方法,这个方法的作用是封装创建进程的命令。
//ZygoteProcess.java
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid,
@Nullable final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
boolean useUsapPool,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
//封装创建进程的命令
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
argsForZygote.add("--mount-external-read");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
argsForZygote.add("--mount-external-write");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
argsForZygote.add("--mount-external-full");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
argsForZygote.add("--mount-external-installer");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
argsForZygote.add("--mount-external-legacy");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}
if (instructionSet != null) {
argsForZygote.add("--instruction-set=" + instructionSet);
}
if (appDataDir != null) {
argsForZygote.add("--app-data-dir=" + appDataDir);
}
if (invokeWith != null) {
argsForZygote.add("--invoke-with");
argsForZygote.add(invokeWith);
}
if (startChildZygote) {
argsForZygote.add("--start-child-zygote");
}
if (packageName != null) {
argsForZygote.add("--package-name=" + packageName);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
Collections.addAll(argsForZygote, extraArgs);
}
synchronized(mLock) {
//openZygoteSocketIfNeeded(abi)会先判断是否需要创建客户端socket,如果已经创建则返回ZygoteState对象。
//实际上这个时候ZygoteState对象在ZygoteProcess.preloadDefault()被调用后已经创建了,
//这个我们已经在Socket客户端小节中讲过。
//zygoteSendArgsAndGetResult()最后会调用attemptZygoteSendArgsAndGetResult()方法,
//在这个方法中实现了通过字符流发送创建进程命令和接收结果
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useUsapPool,
argsForZygote);
}
}
如注释所述startViaZygote()方法会将方法的参数封装成创建进程的字符串形式的命令,最后通过attemptZygoteSendArgsAndGetResult()方法发送给socket 服务端。
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
Slog.d(LOG_TAG, "attemptZygoteSendArgsAndGetResult, msgStr: " + msgStr);
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
//通过输出字符流将命名发送给服务端
zygoteWriter.write(msgStr);
zygoteWriter.flush();
Process.ProcessStartResult result = new Process.ProcessStartResult();
//读取服务端返回的进程创建后分配的pid
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}
以上就是冷启动App时,客户端发送创建进程请求的过程,接下来我们看下服务端是如何响应的。
在Zygote Socket 服务端章节,我们知道在ZygoteServer.runSelectLoop()方法中会一直等待客户端发送过来的命令,而处理客户端的命令是由ZygoteConnection.processOneCommand()实现的,我们看下这个方法
//ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//读取命令
args = Zygote.readArgumentList(mSocketReader);
// TODO (chriswailes): Remove this and add an assert.
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
// readArgumentList returns null only when it has reached EOF with no available
// data to read. This will only happen when the remote socket has disconnected.
if (args == null) {
isEof = true;
return null;
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
parsedArgs = new ZygoteArguments(args);
// 查询abi列表命令
if (parsedArgs.mAbiListQuery) {
handleAbiListQuery();
return null;
}
// 查询pid的命令
if (parsedArgs.mPidQuery) {
handlePidQuery();
return null;
}
//是否采用pre-fork方式
if (parsedArgs.mUsapPoolStatusSpecified) {
return handleUsapPoolStatusChange(zygoteServer, parsedArgs.mUsapPoolEnabled);
}
// 预加载资源和类命令
if (parsedArgs.mPreloadDefault) {
handlePreload();
return null;
}
// 预加载apk命令
// 关于命令含义可参考ZygoteArguments中的定义
if (parsedArgs.mPreloadPackage != null) {
handlePreloadPackage(parsedArgs.mPreloadPackage, parsedArgs.mPreloadPackageLibs,
parsedArgs.mPreloadPackageLibFileName, parsedArgs.mPreloadPackageCacheKey);
return null;
}
if (canPreloadApp() && parsedArgs.mPreloadApp != null) {
byte[] rawParcelData = Base64.getDecoder().decode(parsedArgs.mPreloadApp);
Parcel appInfoParcel = Parcel.obtain();
appInfoParcel.unmarshall(rawParcelData, 0, rawParcelData.length);
appInfoParcel.setDataPosition(0);
ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(appInfoParcel);
appInfoParcel.recycle();
if (appInfo != null) {
handlePreloadApp(appInfo);
} else {
throw new IllegalArgumentException("Failed to deserialize --preload-app");
}
return null;
}
if (parsedArgs.mApiBlacklistExemptions != null) {
return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions);
}
if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
|| parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) {
return handleHiddenApiAccessLogSampleRate(zygoteServer,
parsedArgs.mHiddenApiAccessLogSampleRate,
parsedArgs.mHiddenApiAccessStatslogSampleRate);
}
if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: "
+ "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
+ ", effective=0x" + Long.toHexString(parsedArgs.mEffectiveCapabilities));
}
Zygote.applyUidSecurityPolicy(parsedArgs, peer);
Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
int[][] rlimits = null;
if (parsedArgs.mRLimits != null) {
rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
}
int[] fdsToIgnore = null;
if (parsedArgs.mInvokeWith != null) {
try {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
} catch (ErrnoException errnoEx) {
throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
}
}
int [] fdsToClose = { -1, -1 };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
fdsToClose[0] = fd.getInt$();
}
fd = zygoteServer.getZygoteSocketFileDescriptor();
if (fd != null) {
fdsToClose[1] = fd.getInt$();
}
fd = null;
//创建进程命令,forkAndSpecialize()方法最终实现是调用了Linux系统fork()函数创建进程。
//如果创建成功,fork()函数会返回两次pid;一次是在父进程中返回子进程的pid(不为0),一次是在子进程中返回pid(值为0)
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.mTargetSdkVersion);
try {
if (pid == 0) {
// 在子进程中,setForkChild()方法会将ZygoteServer中的mIsForkChild设为true。
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
//在父进程中,
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
//注意这里返回的是null
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
processOneCommand()方法并不只是处理创建进程的逻辑,还处理包括查询abi列表、pid、是否采用USAP方式创建进程等功能。这里我们看下非USAP方式创建进程的过程,也就是上面调用Zygote.forkAndSpecialize()及之后的过程。Zygote.forkAndSpecialize()方法最终会调用Linux系统函数fork()创建进程,到此我们终于看到进程创建的地方了,在创建进程完成后会先后从父进程和子进程中返回,分别调用handleParentProc()和handleChildProc()方法,我们看下这两个方法。
//ZygoteConnection.java
private void handleParentProc(int pid, FileDescriptor[] descriptors, FileDescriptor pipeFd) {
if (pid > 0) {
setChildPgid(pid);
}
if (descriptors != null) {
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
}
boolean usingWrapper = false;
// 省略部分代码......
try {
mSocketOutStream.writeInt(pid);
mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
throw new IllegalStateException("Error writing to command socket", ex);
}
}
handleParentProc()方法比较简单,它的主要作用是将进程的pid和usingWapper变量的值通过输出流告诉客户端,客户端在ZygoteProcess.attemptZygoteSendArgsAndGetResult()方法中会去读取这两个值。
Process.ProcessStartResult result = new Process.ProcessStartResult();
//读取服务端返回的进程创建后分配的pid
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
接下来我们继续看下handleChildProc()实现
//ZygoteConnection.java
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
closeSocket();
if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.mNiceName != null) {
Process.setArgV0(parsedArgs.mNiceName);
}
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 {
//isZygote值却决于创建进程命令参数是否包含‘--start-child-zygote’
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
这里我们看下isZygote值为false的情况(实际上为true的情况最终都会调用到RuntimeInit.findStaticMain()方法),Zygote.zygoteInit()会调用RuntimeInit.applicationInit()方法,我们直接看下applicationInit()方法。
//RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
nativeSetExitWithoutCleanup(true);
//设置虚拟机的堆内存利用率的百分比,当实际的利用率偏离这个百分比的时候,
//虚拟机会在GC的时候调整堆内存大小,让实际占用率向个百分比靠拢,默认为0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
//设置目标sdk版本
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
这个方法设置了虚拟机堆内存利用率百分比和目标SDK版本,然后调用了findStaticMain()方法,我们接着看下这个方法,
//RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
return new MethodAndArgsCaller(m, argv);
}
这个方法比较简单,就是通过反射的方式找到参数className
类的main()函数,并传入argv参数,在冷启动app的情况下,参数className的值为android.app.ActivityThread
;然后封装成MethodAndArgsCaller对象返回。MethodAndArgsCaller实现了Ruannable接口,在run方法中调用了Method.invoke()方法,也就是会真正调用className
的main()方法。或许你就有个疑问了,这个任务的run方法是什么时候被调用的,在一个新的线程或者线程池中执行的吗。我们知道ZygoteConnection.processOneCommand()方法中在子进程的情况下会调用zygoteServer.setForkChild()
并返回这个MethodAndArgusCaller对象。那我们现在回过头来看下processOneCommand()被调用的地方——ZygoteServer.runSelectLoop()。
//ZygoteServer.java
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
//省略部分代码.....
ZygoteConnection connection = peers.get(pollIndex);
// 处理客户端发送过来的命令
final Runnable command = connection.processOneCommand(this);
// 在processOneCommand()方法中,子进程情况下会将mIsForkChild设置为true
// 所以从子进程中返回时会返回command对象。
if (mIsForkChild) {
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
if (command != null) {
throw new IllegalStateException("command != null");
}
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
//省略部分代码.....
}
}
既然在子进程中runSelectLoop()方法会返回Runnable实例command
,那我们再看下runSelectLoop()被调用的地方
//ZygoteInit.java
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 {
// 省略部分代码.....
// 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 exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// 在子进程中从runSelectLoop()返回后,调用Runnable.run()方法,实际上就是调用了MethodAndArgsCaller的run()方法
if (caller != null) {
caller.run();
}
}
现在我们知道了MethodAndArgsCaller.run()方法调用的时机了,以App冷启动为例,后面经过一系列方法调用,最后最调用到Activity StackSupervisor.realStartActivityLocked(),再之后的流程就和《Android Activity启动过程分析》启动流程分析章节中从realStartActivityLocked()方法开始是一样的,后面的流程就不在重复了;至此服务端响应创建进程命令就分析完了,最后附上服务端处理创建进程和启动Activity的流程时序图供大家参考。
讲了这么一大堆,实际上总结起来就下面几点