hi,粉丝朋友们!
今天有个学员朋友在千里马的android framework实战开发时候,使用的是最新android13代码的,相比以前的版本这块Zygote fork新进程还是有较大的差异。
下面我们就来重点分析一下android13的zygote的fork App进程源码分析,主要讲解和以前版本差异部分:
上图就是老版本的一个fork情况
但是新版本android 13后在ZygoteConnection.processCommand的部分开始有很大差异
//这里android 13要非常特殊应用才可以进入这里,一般都是else
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);
//省略
} else {
//普通app都是走这里
ZygoteHooks.preFork();
Runnable result = Zygote.forkSimpleApps(argBuffer,
zygoteServer.getZygoteSocketFileDescriptor(),
peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);
//省略
}
哈哈,注意一般app都是走Zygote.forkSimpleApps这个,但是你要是对这个方法直接打印会发现它并不是个一次性方法,进入后马上出来,这里forkSimpleApps方法名字其实和它的实际行动不太搭,所以这里大家特别注意不要被它的名字迷惑,以为每次 fork新的app进程,这里就会进入一次forkSimpleApps
来看看forkSimpleApps的特殊
static @Nullable Runnable forkSimpleApps(@NonNull ZygoteCommandBuffer argBuffer,
@NonNull FileDescriptor zygoteSocket,
int expectedUid,
int minUid,
@Nullable String firstNiceName) {
boolean in_child =
argBuffer.forkRepeatedly(zygoteSocket, expectedUid, minUid, firstNiceName);
if (in_child) {
return childMain(argBuffer, /*usapPoolSocket=*/null, /*writePipe=*/null);
} else {
return null;
}
}
这里看着没有啥东西,就是调用了个argBuffer.forkRepeatedly方法,不过这个方法就可以看出点有循环的意思
boolean forkRepeatedly(FileDescriptor zygoteSocket, int expectedUid, int minUid,
String firstNiceName) {
try {
return nativeForkRepeatedly(mNativeBuffer, zygoteSocket.getInt$(),
expectedUid, minUid, firstNiceName);
} finally {
Reference.reachabilityFence(mSocket);
Reference.reachabilityFence(zygoteSocket);
}
}
这里又调用到了nativeForkRepeatedly
jboolean com_android_internal_os_ZygoteCommandBuffer_nativeForkRepeatedly(
JNIEnv* env,
jclass,
jlong j_buffer,
jint zygote_socket_fd,
jint expected_uid,
jint minUid,
jstring managed_nice_name) {
//省略部分
do {
if (credentials.uid != expected_uid) {
return JNI_FALSE;
}
n_buffer->readAllLines(first_time ? fail_fn_1 : fail_fn_n);
n_buffer->reset();
int pid = zygote::forkApp(env, /* no pipe FDs */ -1, -1, session_socket_fds,
/*args_known=*/ true, /*is_priority_fork=*/ true,
/*purge=*/ first_time);//这里进行zygote::forkApp
if (pid == 0) {
return JNI_TRUE;//新fork的进程直接退出
}
//zygote自身继续监听数据循环
for (;;) {//注意这里死循环
// Poll isn't strictly necessary for now. But without it, disconnect is hard to detect.
//一般就会一直阻塞这里,等待下一个要fork进程时候就可以继续执行
int poll_res = TEMP_FAILURE_RETRY(poll(fd_structs, 2, -1 /* infinite timeout */));
if ((fd_structs[SESSION_IDX].revents & POLLIN) != 0) {
if (n_buffer->getCount(fail_fn_z) != 0) {//有新的进程fork时候,会break出这个死循环
break;
} // else disconnected;
}
//省略
}
first_time = false;
} while (n_buffer->isSimpleForkCommand(minUid, fail_fn_n));
ALOGW("forkRepeatedly terminated due to non-simple command");
n_buffer->logState();
n_buffer->reset();
return JNI_FALSE;
}
上面即可以看出,这一部分的循环数据监测工作放到的native层面进行了