Android系統啟動
對於Android系統整個啟動過程來說,基本可以劃分成三個階段:Bootloader引導,Linux內核啟動,Android啟動。如下的流程圖可以看出三個階段的執行順序和聯繫(一張圖看不懂就看三張圖)。
Bootloader引導
BootLoader是在操作系統運行之前運行的一段程序,它可以使系統的軟硬件環境帶到一個合適的狀態,為運行操作系統做好準備。它的任務就是把OS拉起來運行,啟動Linux內核,我們對這一塊的內容並不太注意。
Linux內核啟動
Linex內核啟動後會初始化環境/驅動等,接著會啟動init的進程。
1.Init進程的啟動
init進程,它是一個由內核啟動的用戶級進程。內核自行啟動(已經被載入內存,開始運行,並已初始化所有的設備驅動程序和數據結構等)之後,就通過啟動一個用戶級程序init的方式,啟動init進程。
啟動過程是代碼
system\core\init\init.cpp
的主要函數的執行過程。在函數中執行了:文件夾建立,掛載,rc文件解析,屬性設置,啟動服務,執行動作,socket監聽等。在rc文件解析中會啟動ServiceManager服務和Zygote進程。2. ServiceManager服務
ServiceManager用來管理系統中所有的binder服務,不管是本地的c ++實現的還是java語言實現的都需要這個進程來統一管理,最主要的管理就是,註冊添加服務,獲取服務。所有的服務使用前都必須先在ServiceManager中進行註冊。
3. Zygote進程的啟動
Zygote進程啟動才算建立起真正的Android的運行空間。不過過程不會直接啟動Zygote進程,而是使用app_process命令來通過Android Runtime來啟動,Android Runtime會啟動第一個Davlik虛擬機,並調用Zygote的主要方法,啟動服務.dir / system / core / rootdir / init.zygote32.rc:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
Android的啟動
1. Zygote啟動
Zygote從框架/ base / cmds / app_process / app_main.cpp中的主開始,並建立Android運行時。
//建立 Android runtime
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
// 然后调用 Java 的 ZygoteInit
// dir/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// 随后
//登记Listen端口
registerZygoteSocket();
//启动SystemServer服务
startSystemServer();
2.系統服務器啟動
在上一步中調用了startSystemServer,Zygote上叉了一個進程:com.android.server.SystemServer。於是Java中的SystemServer就建立起來了,SystemServer的主函數中會啟動一些服務:
startBootstrapServices();
startCoreServices();
startOtherServices();
在startBootstrapServices()中看到
mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
ActivityManagerService.Lifecycle是ActivityManagerService的靜態內部類,持有ActivityManagerService實例。所以ActivityManagerService是在這裡被啟動的來。
當然還有很多的其他服務(PackageManagerService,PowerManagerService,DisplayManagerService,BatteryService等)也都會被啟動起來。
在所有的服務啟動完成後,會調用Service.systemReady()來通知各對應的服務,系統已經就緒。
3.ActivityManagerService啟動
在ActivityManagerService的systemReady()方法中有:
startHomeActivityLocked();
mStackSupervisor.startHomeActivity()
這樣主頁程序被啟動起來,整個機器人的啟動過程就完成了,進入用戶界面。
霸氣的分割線
Android的init進程啟動過程
0.前言
Android中的內核啟動後,內核會啟動第一個用戶級別的進程:init,它是一個由內核啟動的第一個用戶級進程。我們可以通過
adb shell ps | grep init
來查看他的pid為1.接下來從源碼的角度看看的init進程啟動的時候做了什麼?
init進程的源碼在android源碼的目錄中。我們看到該目錄下有一個Android.mk文件,至少看到如下內容,告訴我們會生成一個init的可執行文件。
LOCAL_MODULE:= init
include $(BUILD_EXECUTABLE)
而init的入口主函數是在init.cpp文件中定義的。
1.入口
1.命令行解析
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
看門狗和uevent命令已經集成到了init,它們在/ sbin目錄,是一個鏈接文件,直接鏈接到/ init,所以當執行/ sbin / eventd或/ sbin / watchdogd時,將會進入對應的ueventd_main或watchdogd_main入口點.ueventd守護進程負責解析/ueventd.rc文件,並創建相應的設備結點等.watchdogd守護進程負責定時向“/ dev / watchdog”執行寫操作,以判斷系統是否正常運行。這兩個進程不是本文討論的重點,所以先忽略。
2.掛載根文件系統的目錄
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
分別掛載proc和和sysfs文件系統到/ proc和/ sys目錄
close(open(“/ dev / .booting”,O_WRONLY | O_CREAT | O_CLOEXEC,0000)); 在/ dev目錄創建一個空文件.booting來表示正在執行
初始化InitKernelLogging(argv); 重定向標準輸入,標準輸出,標準錯誤輸出到/ dev / null
selinux_initialize(is_first_stage)加載SELinux策略,後面有一些初始化文件上下文的操作等
close(open(“/ dev / .booting”,O_WRONLY | O_CREAT | O_CLOEXEC,0000)); 在/ dev目錄創建一個空文件.booting來表示正在執行
初始化InitKernelLogging(argv); 重定向標準輸入,標準輸出,標準錯誤輸出到/ dev / null
selinux_initialize(is_first_stage)加載SELinux策略,後面有一些初始化文件上下文的操作等
3.解析init.rc文件
Parser& parser Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique());
parser.AddSectionParser("on", std::make_unique());
parser.AddSectionParser("import", std::make_unique());
parser.ParseConfig("/init.rc");
- 3.1 init.rc文件是以塊(section)為單位組織的,一個section包含多行.section分為兩大類:分別為“服務(service)”和“行為(action)”。
- 3.2“服務”塊以關鍵字“service”開始,表示啟動某個進程的方式和參數,“行為”塊以關鍵字“on”開始,表示一堆命令的集合。上“或”上“或”服務“開始,直到下一個”,“結束,中間所有行都屬於這個”塊“。
- 3.3上面在解析init.rc文件時使用了Parser類(在init目錄下的init_parser.h中定義),初始ServiceParser用來解析“service”塊,ActionParser用來解析“on”塊,ImportParser用來解析“ import“塊,”import“是用來引入一個init配置文件,來擴展當前配置的。
- 3.4解析器解析init.rc文件,/ init.rc文件是dir / system / core / rootdir / init.rc。
- 3.5 dir / system / core / init / readme.txt中對init文件中的所有關鍵字做了介紹,主要包含了操作,命令,服務,選項和導入等
- 3.6在ParseConfig解析完init腳本後,init會依次執行幾個重要的階段:3.6.1在早期階段
am.QueueEventTrigger("early-init"); 执行 on early-init 内容,主要包括 start ueventd 等
3.6.2。在init階段am.QueueEventTrigger("init"); 执行 on init 内容,主要包括 创建/挂载一些目录,以及 symlink 等
3.6.3。在充電器/晚期初始階段``` // Don't mount filesystems or start core system services in charger mode. std::string bootmode = property_get("ro.bootmode"); if (bootmode == "charger") { am.QueueEventTrigger("charger"); } else { am.QueueEventTrigger("late-init"); } ```
如果是充電模式下啟動就會執行充電器內容,否則執行on late-init內容,在init.rc的late-init中看到很多trigger(觸發器),用於執行對應的Action。``` trigger late-fs # Now we can mount /data. File encryption requires keymaster to decrypt # /data, which in turn can only be loaded when system properties are present. trigger post-fs-data # Load persist properties and override properties (if enabled) from /data. trigger load_persist_props_action # Remove a file to wake up anything waiting for firmware. trigger firmware_mounts_complete trigger early-boot trigger boot ```
從最後兩行可以看出,late-init觸發了早啟動和開機兩個Action。3.6.4。在啟動階段在開機的最後class_start核心會啟動類為核心的服務,這些服務包括ueventd,logd,healthd,adbd(禁用),lmkd(LowMemoryKiller),servicemanager,vold,debuggerd,surfaceflinger,bootanim(禁用)等3.6.5。主服務的啟動在主函數後面的while循環中,調用execute_one_command依次執行操作隊列中的命令``` while (true) { if (!waiting_for_exec) { am.ExecuteOneCommand(); restart_processes(); } } ```
在/init.rc的開頭部分``` import /init.environ.rc import /init.usb.rc import /init.${ro.hardware}.rc import /init.usb.configfs.rc import /init.${ro.zygote}.rc ```
通過ro.zygote的屬性導入對應的zygote的rc文件,通過adb shell getprop ro.zygote查看得到zygote64_32,所以導入的是/init.zygote64_32.rc文件,該文件中定義的zygote如下:``` service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main priority -20 socket zygote 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 writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks ```
可以看到zygote的class是main,它是在on nonencrypted時被啟動的``` on nonencrypted # A/B update verifier that marks a successful boot. exec - root -- /system/bin/update_verifier nonencrypted class_start main class_start late_start ```
注:但在Android 7.0中,對該機製做了一些改變。
單一的init * .rc,被拆分,服務根據其二進製文件的位置(/ system,/ vendor,/ odm)定義到對應分區的etc / init目錄中,每個服務一個rc文件。與該服務相關的觸發器,操作等也定義在同一個rc文件中。/system/etc/init,包含系统核心服务的定义,如 SurfaceFlinger、MediaServer、Logcatd 等。 /vendor/etc/init, SOC 厂商针对 SOC 核心功能定义的一些服务。比如高通、MTK 某一款 SOC 的相关的服务。 /odm/etc/init,OEM/ODM 厂商如小米、华为、OPP 其产品所使用的外设以及差异化功能相关的服务。
查看Android 7.0虛擬機的/ system / etc / init如下上面的ServiceManager這個服務也從init.rc中拆分出來了。
4.啟動完成
至此,init進程已經啟動完成,一些重要的服務如核心服務和主服務也都啟動起來,並啟動了zygote(/ system / bin / app_process64)進程,zygote初始化時會創建虛擬機,啟動SystemServer等,它的啟動過程也是非常複雜。
霸氣的分割線
Zygote的啟動過程
0.前言
上節文章的最後說到了init以service的方式啟動了Zygote進程。這節文章主要講Zygote進程的啟動流程。
對於Zygote進程的描述如下:
在Android中,zygote是整個系統創建新進程的核心.Zygote進程在內部會先啟動Dalvik虛擬機,繼而加載一些必要的系統資源和系統類,最後進入一種監聽狀態。在後續的運作中,當其他系統模塊(比如AMS)希望創建新進程時,只需向Zygote進程發出請求,Zygote進程監聽到該請求後,會相應地“分裂”出新的進程,於是這個新進程在初生之時,就先天具有了自己的Dalvik虛擬機以及系統資源。
1.啟動流程
/init.zygote64_32.rc文件中啟動Zygote的內容如下:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
socket zygote 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
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
在dir / system / core / rootdir /目錄下可以看到init.zygote32.rc,init.zygote32_64.rc,init.zygote64.rc,init.zygote64_32.rc等文件,這是因為Android5.0開始支持64位的編譯,所以Zygote進程本身也有32位和64位版本。
從上面定義看到Zygote進程的可執行文件是frameworks / base / cmds / app_process / app_main.cpp。
接下來分析主函數的流程。
1.1。創建AppRuntime對象
AppRuntime是在app_process中定義的類,繼承了系統的AndroidRuntime類,AndroidRuntime類的主要作用是創建和初始化虛擬機。
AppRuntime是在app_process中定義的類,繼承了系統的AndroidRuntime類,AndroidRuntime類的主要作用是創建和初始化虛擬機。
1.2。解析啟動參數
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;
}
}
從init.rc文件中傳入的參數是-Xzygote / system / bin --zygote --start-system-server --socket-name = zygote,解析後:
zygote = true;
niceName = zygoe;
startSystemServer = true;
1.3。執行ZygoteInit類
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.");
return 10;
}
Zygote經過解析參數後為true,所以會執行runtime.start(“com.android.internal.os.ZygoteInit”,args,zygote);
AndroidRuntime的start方法實現在dir / frameworks / base / core / jni / AndroidRuntime.cpp中,
AndroidRuntime的start方法實現在dir / 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& options, bool zygote)
{
// 启动虚拟机,注册jni等
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
...
}
這個方法會啟動Android運行環境,意味著它會啟動Android虛擬機,並調用參數中className中的主方法。
從傳入的com.android.internal.os.ZygoteInit類中找到主函數,即調用ZygoteInit。 java類中的main方法.AndroidRuntime及之前的方法都是native的方法,而此刻調用的ZygoteInit.main方法是java的方法,到這裡我們就進入了java的世界。
從傳入的com.android.internal.os.ZygoteInit類中找到主函數,即調用ZygoteInit。 java類中的main方法.AndroidRuntime及之前的方法都是native的方法,而此刻調用的ZygoteInit.main方法是java的方法,到這裡我們就進入了java的世界。
調用示意圖如下:
1.4。ZygoteInit的主要方法
ZygoteInit定義在dir / frameworks / base / core / java / com / android / internal / os / ZygoteInit.java中。
public static void main(String argv[]) {
try {
...
registerZygoteSocket(socketName);
preload();
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
runSelectLoop(abiList);
...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
主要工作:
- 註冊受精卵的插座監聽端口,應用接收啟動應用程序的消息
- 調用預載()方法加載系統資源,包括預加載類,框架資源等
- 調用startSystemServer()方法啟動SystemServer進程
- 調用runSelectLoop()方法進入監聽和接收消息循環
可見SystemServer是受精卵啟動的第一個進程。
以上學習了Android系統的啟動流程。
沒有留言:
張貼留言