極力推薦文章:歡迎收藏
Android 干貨分享
本篇文章主要介紹 Android Zygote 啟動分析 知識點,通過閱讀本篇文章,您將收獲以下內容:
一、 Android 系統基本服務
二、虛擬機創建和第一個Java 程序引導
三、Dalvik 虛擬機基本配置
四、Zygote 啟動流程
五、Zygote 啟動分析
六、Zygote 創建system_server主要方法
七、Zygote 創建System_server 分析
八、Zygote 創建應用
九、Zygote 創建應用流程
十、Zygote 預加載資源
十一、Zygote 預加載的目的
十二、優化Zygote 啟動方法: 線程池
十三、fork SystemServer
Zygote
服務時通過 init.rc
進程啟動的,Zygote
的 classname
為main
.
init.rc
文件配置代碼如下:
... ...
on nonencrypted
class_start main
class_start late_start
on property:sys.init_log_level=*
loglevel ${sys.init_log_level}
... ...
詳細可以參考 init.rc
啟動分析。
Android 9.0 系統啟動流程
一、 Android 系統基本服務
Android 系統包含netd
、servicemanager
、surfaceflinge
、zygote
、media
、installd
、bootanimation
等基本服務,具體作用請看下圖。
二、虛擬機創建和第一個Java 程序引導
為了讓APK
在不同的虛擬機都可以運行,Google
采取了適配器模式,在讓虛擬機運行之前先執行 dexopt
,即將dex
文件優化成odex
文件,可以讓虛擬機更加優化的執行。
在ART
虛擬機中,dexopt
將dex
文件優化成二進制格式的問題,從而可以讓ART
虛擬機執行。
dexopt
會調用dex2oat
進行優化,dex2oat
的任務是將原來的dex
文件進行預翻譯,從而可以加快app
運行的時間,但是由於某些app
比較復雜,所以優化的時間就比較長。
優化是以dex 文件中的Method 方法為單位,dex2oat
在優化時候,會根據需求優化一定量的Method,即不是所有的Method 都回翻譯成oat模式。
三、Dalvik 虛擬機基本配置
在Android
系統中,Dalvik
虛擬機 和ART
、應用程序進程,以及運行系統的關鍵服務SystemServer
進程都是由 Zygote
進程創建孵化的。
Dalvik 虛擬機基本配置如下:
四、Zygote 啟動流程
Zygote
是由 init.rc
腳本啟動,在init
腳本中,我們可以看到會導入import /init.${ro.zygote}.rc
腳本
# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
... ...
import /init.${ro.zygote}.rc
... ...
在 system/core/rootdir
目錄下,會根據ro.zygote
屬性值不同,啟動不同的腳本,主要包含以下四個zygote
腳本。
- 1.init.zygote32.rc 支持32為系統
- 2.init.zygote32_64.rc
- 3.init.zygote64.rc
- 4.init.zygote64_32.rc
五、Zygote 啟動分析
六、Zygote 創建system_server主要方法
七、Zygote 創建System_server 分析
八、Zygote 創建應用
九、Zygote 創建應用流程
十、Zygote 預加載資源
十一、Zygote 預加載的目的
十二、優化Zygote 啟動方法: 線程池
Zygote 啟動優化前提:
-
1:加載類和資源是可重入操作,所以在並行模式下,不存在互斥的場景
-
2:Android提供了Executors和ExecutorService多線程類,因此可以使用多線程來加載類和資源。
-
3:硬件平台最好是多核,否則加速也不明顯;
Zygote 啟動優化實質:
使我們的進程最大限度的搶占CPU
十三、fork SystemServer
經過一系列初始化后,在ZygoteInit
類中 forkSystemServer
,為啟動SystemServer
做准備。ZygoteInit.java
代碼路徑如下:alps\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
/**
* Prepare the arguments and forks for the system server process.
*
* Returns an {@code Runnable} that provides an entrypoint into system_server code in the
* child process, and {@code null} in the parent.
*/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
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,
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);
} 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 */
String args[] = {
"--setuid=1000",
"--setgid=1000",
/// M: [Wi-Fi Hotspot Manager] system_server add dhcp (1014) group to access
/// "/data/misc/dhcp/dnsmasq.leases"
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1014,1018,1021,1023," +
"1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} 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;
}
至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!