前言java
研究過程當中參考了不少的文章,這篇源碼分析,多是全網最全的Zygote
源碼分析了android
若是以爲這篇源碼分析太幹
,也能夠先看一下後續的相關總結,戳juejin.im/post/5da532…,及B站視頻講解ios
福利活動c++
由Android研習社
和機械工業出版社
聯合發起的贈書活動正在進行中,歡迎你們戳點擊連接參與shell
咱們都知道Android中非特殊進程(除init進程和Zygote進程外的進程,源碼中稱其爲unspecialized app process
),都是由Zygote
fork出來的子進程,包括SystemServer,也是由Zygote
fork出來的bash
這篇文章咱們主要來探討如下幾個問題網絡
這些問題咱們在接下來的源碼分析中來找找答案架構
咱們首先來看下,Zygote進程是如何被啓動起來的app
咱們仍是首先從init.rc
中引用的zygote.rc
中入手來看,源碼中是找不到的,咱們從編譯好的文件中找less
WORKING_DIRECTORY/out/target/product/generic_x86/root/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
複製代碼
我們重點來看前面幾行
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
從這裏,咱們看到zygote的可執行文件所在的位置應該是/system/bin/app_process
,那源碼應該也有一個app_process
的目錄,上次Bilibili技術分享第一期中也提到了,zygote對應的源碼實際上是app_process
的代碼
咱們接着來找到
./frameworks/base/cmds/app_process/app_main.cpp
咱們從app_main
的入口函數來看
int main(int argc, char* const argv[])
{
...
//建立AppRuntime,AppRuntime是AndroidRuntime的子類對象
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); //
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
...
bool known_command = false;
int i;
for (i = 0; i < argc; i++) {
...
runtime.addOption(strdup(argv[i])); //把Zygote.rc中的參數添加到AppRuntime,也就是AndroidRuntime中
...
}
// 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.rc解析傳進來的參數,進行對比
zygote = true; //須要執行zygote的指令
niceName = ZYGOTE_NICE_NAME; //給 nicename 賦值爲zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; //爲startSystemServer的標誌爲賦值
} else if (strcmp(arg, "--application") == 0) {
application = true; //根據參數判斷是否爲application
} 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;
}
}
Vector<String8> args;
//若是是zygote,則className爲空,因此此處其實是判斷是否爲zygote的進程
if (!className.isEmpty()) { //判斷非zygote模式時,只須要傳遞application的參數
// We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. // // The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name. args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); if (!LOG_NDEBUG) { String8 restOfArgs; char* const* argv_new = argv + i; int argc_new = argc - i; for (int k = 0; k < argc_new; ++k) { restOfArgs.append("\""); restOfArgs.append(argv_new[k]); restOfArgs.append("\" "); } ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string()); } } else { //classname爲空,當前爲zygote模式 // We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {//獲取支持的CPU指令集
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
//此處爲zygote模式,須要把全部參數都傳遞過去
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {//niceName不爲空,說明是zygote模式
runtime.setArgv0(niceName.string(), true /* setProcName */);//此處註釋也說明了,這裏是設置進程名
}
if (zygote) {//若是是zygote模式
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//調用zygoteInit函數,並把當前的參數傳遞過去
} else if (className) {//若是是非zygote模式
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);//調用RuntimeInit函數
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
複製代碼
這篇文章的目的是分析zygote的流程,那咱們暫時只關心zygote相關的邏輯
函數最後調用了ZygoteInit
,咱們看看這個類主要作了什麼
/framework/base/core/java/com/android/internal/os/ZygoteInit.java
按照以前的套路,咱們先找到入口函數main
@UnsupportedAppUsage
public static void main(String argv[]) {
// Server socket class for zygote processes.
ZygoteServer zygoteServer = null; //用來管理和子進程通訊的socket服務端
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation(); //這裏其實只是設置一個標誌位,爲建立Java線程時作判斷處理,若是是zygote進程,則不須要開啓線程
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0); //爲zygote進程設置pgid(Process Group ID),詳見:`https://stackoverflow.com/questions/41498383/what-do-the-identifiers-pid-ppid-sid-pgid-uid-euid-mean`
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { //獲取系統屬性,判斷系統重啓完成
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";//判斷當前進程是64位程序仍是32位程序,並設置標記
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
RuntimeInit.enableDdms();//註冊到ddms服務端,內部調用`DdmServer.registerHandler()`
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])) { //參數重包含`start-system-server`
startSystemServer = true; //設置標誌爲位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);//根據socketName判斷是不是primaryZygote,可能還有secondZygote
if (abiList == null) { //若是支持架構爲空,直接拋出異常
throw new RuntimeException("No ABI list supplied.");
}
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize(); //調用ZygoteHooks.gcAndFinalize()進行垃圾回收
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false, 0);
Zygote.initNativeState(isPrimaryZygote);//jni調用初始化zygote的狀態,是否爲isPrimaryZygote
ZygoteHooks.stopZygoteNoThreadCreation(); //結束zygote建立,其實內部是調用`runtime`給`zygote_no_threads_`賦值爲false,爲建立本地線程作準備
zygoteServer = new ZygoteServer(isPrimaryZygote); //建立zygoteServer,爲其餘進程初始化建立時與zygote通訊作準備
if (startSystemServer) { //判斷是否須要startSystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//經過fork的方式開啓zygote的子進程,systemServer,並返回一個Runnale對象
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {//若是是zygote進程,則r==null,若是不是zygote進程,也就是systemServer進程,則執行下面的代碼
r.run();
return;
}
}
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); //zygote進程進入死循環中,來獲取子進程發送的消息
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket(); //若是發生異常,則說明zygote初始化失敗,zygoteServer也須要關閉
}
}
// We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run(); } } 複製代碼
zygote的大概流程咱們已經梳理完了,如今咱們來總結一下
zyogte.rc
腳本app_process/appMain.cpp
zygoteInit.java
初始化zygote進程zygoteInit.cpp
完成進程建立runSelectionLoop()
,接收其餘進程發送的消息建立子進程咱們都知道,Android系統中,zyogte進程是Java世界的首個進程(init進程爲頭號進程),是直接經過exec
的系統調用建立的,其餘的進程,包括system_server
,都是zygote進程的子進程,那咱們接下來從源碼的角度來看一下,zygote是如何fork
出system_server
的
public static void main(String argv[]) {
...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) { //若是r不爲空,說明是system_server進程
r.run(); //調用其run方法
return;
}
}
...
}
...
}
複製代碼
由上面的分析咱們看到,根據zygote.rc
的參數,解析出是否須要startSystemServer
,若是爲true,則調用forkSystemServer
來fork出子進程SystemServer,而且執行其返回的Runnable的run()方法,咱們先來看看forkSystemServer
具體作了什麼
/**
* Prepare the arguments and forks for the system server process.
* 爲forkSystemServer進程準備參數,而且建立system server進程
*
* @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) {
//Linux使用POSIX capabilities代替傳統的信任狀模型
long capabilities = posixCapabilitiesAsBits( //設置進程權能
OsConstants.CAP_IPC_LOCK, //容許鎖定共享內存片斷
OsConstants.CAP_KILL, //容許對不屬於本身的進程發送信號
OsConstants.CAP_NET_ADMIN, // 容許執行網絡管理任務:接口、防火牆和路由等
OsConstants.CAP_NET_BIND_SERVICE, //容許綁定到小於1024的端口
OsConstants.CAP_NET_BROADCAST, //容許網絡廣播和多播訪問
OsConstants.CAP_NET_RAW, //容許網絡廣播和多播訪問
OsConstants.CAP_SYS_MODULE, //插入和刪除內核模塊
OsConstants.CAP_SYS_NICE, //容許提高優先級,設置其它進程的優先級
OsConstants.CAP_SYS_PTRACE, //容許配置進程記賬
OsConstants.CAP_SYS_TIME, //容許改變系統時鐘
OsConstants.CAP_SYS_TTY_CONFIG, //容許配置TTY設備
OsConstants.CAP_WAKE_ALARM,
OsConstants.CAP_BLOCK_SUSPEND
);
/* Containers run without some capabilities, so drop any caps that are not available. */
StructCapUserHeader header = new StructCapUserHeader(
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
StructCapUserData[] data; //用戶權能數據
try {
data = Os.capget(header); //獲取進程權能,存儲到data中
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to capget()", ex);
}
capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
/* Hardcoded command line to start the system server */
/*使用硬編碼的方式定義出啓動system server的參數字符串args*/
String args[] = {
"--setuid=1000", //用戶id
"--setgid=1000",//用戶組id
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities, //進程權能
"--nice-name=system_server", //進程niceName
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = null;
int pid; //processId,進程id
try {
parsedArgs = new ZygoteArguments(args); ////建立ZygoteArguments對象,把args解析爲須要的參數
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false); //跟Art虛擬機相關,暫時不作深究
if (profileSystemServer) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
pid = Zygote.forkSystemServer( //fork建立SystemServer
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) { //pid爲0,則說明是zygote進程,進行最後的收尾工做
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
複製代碼
代碼最後調用了Zygote.forkSystemServer()
來建立SystemServer,咱們接着來跟一下
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();//內部調用ART的Runtime對zygote的線程池的線程進行清理
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer( //JNI調用,真正建立systemServer進程的函數
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}
複製代碼
接着跟下去,到c++的本地代碼中 zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
jlong effective_capabilities) {
...
pid_t pid = ForkCommon(env, true,
fds_to_close,
fds_to_ignore);//從zygote進程fork出子進程,並返回processId
...
return pid;
}
複製代碼
到這裏咱們就把相關源碼分析完了,咱們來總結下:
zygote.rc
的相關腳本,獲取startSystemserver
的屬性字段startSystemServer()
forkSystemServer()
,爲當前進程賦予權限,並設置UID,GIDzygote.forkSystemServer
nativeForkSystemServer
完成進程的fork工做這裏咱們只分析zygote相關的源碼,完整流程等分析AMS時一塊兒總結
zygoteInit中,最後調用了zyogteServer的runSelectionLoop()函數,進入一個無限循環中,咱們來看下代碼
Runnable runSelectLoop(String abiList) { //此處使用了selcet IO複用機制,這個咱們之後專門來分析Linux的IO複用機制
...
while (--pollIndex >= 0) {
...
if (pollIndex == 0) {
// Zygote server socket
ZygoteConnection newPeer = acceptCommandPeer(abiList);//建立socket鏈接的服務端
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); //獲取到客戶端鏈接對象ZygoteConnection
final Runnable command = connection.processOneCommand(this); //讀取一個sokcet命令,並fork出子進程,執行子進程的main函數
// 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 processOneCommand 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 processOneCommand. This
// shows up as a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
}
...
}
...
}
}
複製代碼
這裏當pollIndex==0
先調用acceptCommandPeer()
建立sokcet鏈接的服務端,其餘條件下,調用acceptCommandPeer()
獲取一個ZygoteConnect
對象,並執行其processOneCommand()
函數,讀取一個sokcet命令,並fork出子進程,執行子進程的main函數,咱們仍是接着跟一下這個函數
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
ZygoteArguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = Zygote.readArgumentList(mSocketReader); //從sokcet中讀取參數
// TODO (chriswailes): Remove this and add an assert.
descriptors = mSocket.getAncillaryFileDescriptors(); //獲取其附帶的文件描述符
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
...
int pid = -1;
FileDescriptor childPipeFd = null;//子進程,使用管道進行進程間通訊,
FileDescriptor serverPipeFd = null;
parsedArgs = new ZygoteArguments(args); //建立Zygote參數對象
...
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);
//Forks a new VM instance
//建立一個新的VM實例對象,也就是咱們平時說的沙盒隔離機制(sandbox)
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();//設置標誌位mIsForkChild爲true
...
return handleChildProc(parsedArgs, descriptors, 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, descriptors, serverPipeFd);//若是pid>0,則爲子進程設置進程號,不然就是建立失敗
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
複製代碼
這裏根據傳遞過來的參數建立zygoteArgs
對象,並建立出VM虛擬機對象,最終調用handleChildProc()
來建立子進程,繼續跟蹤代碼
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
...
if (parsedArgs.mNiceName != null) { //判斷mNiceName不爲空
Process.setArgV0(parsedArgs.mNiceName); //設置mNiceName爲進程名
}
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) { //判斷參數中mInvokeWith爲空時,使用exec的系統調用開啓進程
...
} else {
if (!isZygote) { //非zygote模式
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else { //zygote模式
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */); //zygoteInit的備選函數,同時初始化Zygote進程
}
}
}
複製代碼
此處咱們只關心由Zyogte進程fork出子進程的狀況,跟蹤zygoteInit()
這個函數
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
...
RuntimeInit.commonInit(); //對runtime進行初始化
ZygoteInit.nativeZygoteInit(); //JNI調用,nativeZygoteInit
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//找到Appde 主函數並初始化調用
}
複製代碼
這裏首先的對Runtime
進行初始化,而後經過JNI對zygote
進行真正的初始化操做,函數代碼以下
static AndroidRuntime* gCurRuntime = NULL;
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit(); //調用AndroidRuntime的zygoteInit
}
複製代碼
這裏是調用了AndroidRuntime
的onZygoteInit()
,此處點進去能夠看到它是一個虛函數,那麼應該是由的子類對象來作的具體實現,以前咱們也分析過,AndroidRuntime
在app_process
的app_main
中又一個子類對象AppRuntime
,咱們來看一下
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
}
...
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();//開啓Bind線程池線程,設置線程名稱
}
...
};
複製代碼
此處建立了一個ProcessState
的對象,並調用了它的startThreadPool()
函數,跟蹤下去能夠發現內部調用了spawnPooledThread
的函數來建立線程並啓動的
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) { //判斷線程已開啓
String8 name = makeBinderThreadName(); //建立Binder線程池名稱
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain); //建立主線程
t->run(name.string()); //執行線程
}
}
複製代碼
handleChildProc()
這一系列代碼執行完畢後,會調用handleParentProc()
對子進程建立狀態進行判斷,若是pid>0
則說明建立成功,到此處咱們子進程以及其相關線程就準備完畢了
如今來總結下
runSelectLoop
,循環讀取消息acceptCommandPeer
建立Sokcet服務端的鏈接對象ZygoteConnection
acceptOneCommand
讀取Soket的消息handleChildProcess
處理子進程的建立zygoteInit.zyogteInit(args...)
把參數傳遞進去app_process/app_main.cpp
的AppRuntime
具體實現中上面咱們分析Zygote流程時涉及到一個類,ZygoteServer
,下面咱們來具體看下,它是如何建立的
在zygote的main
函數中是這麼初始化的
zygoteServer = new ZygoteServer(isPrimaryZygote);
複製代碼
那咱們就從這個構造函數入手
/**
* Initialize the Zygote server with the Zygote server socket, USAP pool server socket, and USAP
* pool event FD.
*
* @param isPrimaryZygote If this is the primary Zygote or not.
*/
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) { //根據zygote.rc中的參數判斷是不是PrimaryZygote
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);//把PRIMARY_SOCKET_NAME賦值給mZygoteSocket
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);//把USAP_POOL_PRIMARY_SOCKET_NAME賦值給mUsapPoolSocket
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);//把SECONDARY_SOCKET_NAME賦值給mZygoteSocket
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);//把USAP_POOL_SECONDARY_SOCKET_NAME賦值給mUsapPoolSocket
}
fetchUsapPoolPolicyProps();
mUsapPoolSupported = true;
}
複製代碼
上面的代碼裏主要是把zygote.rc中的配置取出來,其中涉及到了兩個socket,mZygoteSocket
和mUsapPoolSocket
;也涉及到兩個Zygote,PrimaryZygote
,SecondZygote
可是你可能會奇怪,我們的zygote.rc中,怎麼沒有這個東西呢?我再把這個文件貼一遍
WORKING_DIRECTORY/out/target/product/generic_x86/root/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
複製代碼
惟一跟primary有關的,是socket usap_pool_primary stream 660 root system
,那SecondZygote去哪了呢?
這個跟我們編譯的版本是有關係的,當前編譯的版本中,只支持32爲的應用,因此只有32位的PrimaryZygote
,那我們來看一下我根據源碼編譯的Pixel 2
的Android10系統中有沒有
使用adb shell
查看
cat init.zygote64_32.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
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
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
複製代碼
這裏很清楚的看獲得,64位的zygote是PrimaryZygote
,32位的zygote是SecondZygote
,不一樣的二進制文件能夠由不一樣的Zygote啓動,同時兼容64位和32位程序
咱們再來看看上面提到的兩個Socket是幹什麼的
/**
* Listening socket that accepts new server connections.
*/
private LocalServerSocket mZygoteSocket;
/**
* The name of the unspecialized app process pool socket to use if the USAP pool is enabled.
*/
private LocalServerSocket mUsapPoolSocket;
...
ZygoteServer(boolean isPrimaryZygote) {
...
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
...
}
複製代碼
這裏兩個sokcet的對象的建立都調用的同一個函數createManagedSocketFromInitSocket()
/** Prefix prepended to socket names created by init */
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
/**
* Creates a managed LocalServerSocket object using a file descriptor
* created by an init.rc script. The init scripts that specify the
* sockets name can be found in system/core/rootdir. The socket is bound
* to the file system in the /dev/sockets/ directory, and the file
* descriptor is shared via the ANDROID_SOCKET_<socketName> environment
* variable.
*/
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//拼接爲socket的全路徑名
try {
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); //把獲取到的fileDesc設置進去
return new LocalServerSocket(fd); //返回該Socket對象
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
複製代碼
咱們使用adb來查看下,很容易的查看到兩個Zygote相關的socketFd
咱們來簡單補充一點zygoteHooks
的源碼分析,分析這個問題的目的在於,理清出Dalvik和ART在Android10源碼中的關係
上面的源碼分析中,有幾個地方調用 ZygoteHooks的相關源碼,咱們來簡單分析下
ZygoteHooks.startZygoteNoThreadCreation()
&& ZygoteHooks.stopZygoteNoThreadCreation()
咱們發現這個ZygoteHooks實際上是ART
包下的
./art/runtime/native/dalvik_system_ZygoteHooks.cc
static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
jclass klass ATTRIBUTE_UNUSED) {
Runtime::Current()->SetZygoteNoThreadSection(true);
}
複製代碼
能夠看到這個函數是一個JNI
的接口,內部調用了Runtime
的SetZygoteNoThreadSection
函數
./art/runtime/runtime.h
// Whether zygote code is in a section that should not start threads.
bool zygote_no_threads_;
void SetZygoteNoThreadSection(bool val) {
zygote_no_threads_ = val;
}
bool IsZygoteNoThreadSection() const {
return zygote_no_threads_;
}
複製代碼
能夠看到這裏其實就是設置了一個標誌爲,源碼註釋中也說明了,該字段是爲了區分處於zygote
模式時,不去開啓線程,那咱們來看看這個zygote_no_threads_的字段哪裏使用到了
./art/runtime/runtime.cc
Runtime::Runtime()
: ...
zygote_no_threads_(false),
...
{
...
}
複製代碼
這裏在Runtime構造初始化時,首先把其設置爲false,也就是默認狀況下,Runtime是會去開啓線程的
再來看看返回zygote_no_threads_
的IsZygoteNoThreadSection()
這個函數在哪裏有使用
./art/runtime/native/java_lang_Thread.cc
static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
jboolean daemon) {
// There are sections in the zygote that forbid thread creation.
Runtime* runtime = Runtime::Current();
if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {//判斷是zygote進程,而且IsZygoteNoThreadSection()返回值爲true時
jclass internal_error = env->FindClass("java/lang/InternalError");
CHECK(internal_error != nullptr);
env->ThrowNew(internal_error, "Cannot create threads in zygote");//直接拋出異常,
return; //結束當前函數
}
Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);//若是不是zygote進程,纔去建立本地線程
}
複製代碼
這裏又是一個JNI的接口函數,是用來建立本地線程的(根據類名和方法名也能夠猜到),註釋中也作了說明,只有不是zygote進程時纔會去建立本地線程
stopZygoteNoThreadCreation()
函數也是同樣,一樣是設置標誌爲,設置爲false,那麼就能夠去建立線程了
這裏咱們基本上把zygote
涉及的相關源碼分析完了,下篇文章講會對SystemServer
的相關源碼進行分析。因爲水平有限,寫的不對的還請各位多多指教
原創不易,堅持更難。
若是你想繼續看到我接下來的分享,請經過點讚的方式告訴我,你的鼓勵是我繼續創做的最大動力!