• Android系统启动流程分析


           当按下Android系统的开机电源按键时候,硬件会触发引导芯片,执行预定义的代码,然后加载引导程序(BootLoader)到RAM,Bootloader是Android系统起来前第一个程序,主要用来拉起Android系统程序,Android系统被拉起首先肯定会启动Linux内核。

    备注: 我们再刷机时候,经常看到工具软件会让我们切换bootloader/loader模式,其实就是重新激活bootloader程序,然后再拷贝新的镜像文件重新刷机,就是通过这个程序重新初始化硬件设备,建立内存空间映射。

            我们也知道一个系统肯定会存在一些重要服务和进程来支持整个系统正常运作。  那么Android系统中肯定也存在这种重要进程,如下:  

    序号进程名称概述
    1init进程Linux系统中用户空间第一个进程
    2zygote进程所有App进程的父进程,Zygote Init 
    3system_server进程各大系统服务的载体,forkSystemServer / SystemServer
    4servicemanager进程binder服务的大管家,守护进程循环运行在binder_loop 

    内核启动首先会第一个创建init进程,进程号是1,是所有用户空间的鼻祖,init进程又会启动servicemanager(binder服务管家) 和zygote进程(Java进程鼻祖),zygote进程会创建system_server进程以及各种app进程,大致启动关系如下: 

    源码分析:基于 android10 

    inity源码分析

    /system/core/init/main.cpp  

    1. int main(int argc, char** argv) {
    2. #if __has_feature(address_sanitizer)
    3. __asan_set_error_report_callback(AsanReportCallback);
    4. #endif
    5. if (!strcmp(basename(argv[0]), "ueventd")) {
    6. return ueventd_main(argc, argv);
    7. }
    8. if (argc > 1) {
    9. if (!strcmp(argv[1], "subcontext")) {
    10. android::base::InitLogging(argv, &android::base::KernelLogger);
    11. const BuiltinFunctionMap function_map;
    12. return SubcontextMain(argc, argv, &function_map);
    13. }
    14. if (!strcmp(argv[1], "selinux_setup")) {
    15. return SetupSelinux(argv);
    16. }
    17. if (!strcmp(argv[1], "second_stage")) {
    18. return SecondStageMain(argc, argv);
    19. }
    20. }
    21. return FirstStageMain(argc, argv);
    22. }

    main函数有四个参数入口: 

    1.参数有ueventd进入 uevent_main  

    2. 参数中有subcontext,进入InitLogging和 SubcontextMain 

    3. 参数中有selinux_setup,进入SetupSelinux 

    4. 参数中有second_state,进入SecondStageMain 

    执行顺序如下: 首先会进入FirstStateMain ,主要执行是初始化环境变量,挂载和创建基本的文件系统,并设置访问权限,挂载system、cache、data等系统分区 。 之后进入  SetupSelinxu 根据源码我们可以看到FirstStateMain最后传送了参数selinux_setup 

    1. int FirstStageMain(int argc, char** argv) {
    2. .......
    3. const char* path = "/system/bin/init";
    4. const char* args[] = {path, "selinux_setup", nullptr};
    5. execv(path, const_cast<char**>(args));
    6. // execv() only returns if an error happened, in which case we
    7. // panic and never fall through this conditional.
    8. PLOG(FATAL) << "execv(\"" << path << "\") failed";
    9. return 1;
    10. }

    SetupSelinux主要工作谁设置SELinux安全策略,之后进入SecondStageMain 。  

    1. int SecondStageMain(int argc, char** argv) {
    2. .....
    3. // oom_scroe_adj 为-1000时候相当与关闭OOM机制。 范围 -1000 - 1000
    4. if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
    5. LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
    6. }
    7. // 启用全局Seccomp
    8. GlobalSeccomp();
    9. // 设置所有进程都可以访问的会话密钥环
    10. keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
    11. // 标记booting中
    12. close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
    13. //初始化属性服务,指定文件读取属性
    14. property_init();
    15. .......
    16. // 为第二阶段设置 SELinux。
    17. SelinuxSetupKernelLogging();
    18. SelabelInitialize();
    19. SelinuxRestoreContext();
    20. // android封装好的Epoll开始初始化
    21. Epoll epoll;
    22. if (auto result = epoll.Open(); !result) {
    23. PLOG(FATAL) << result.error();
    24. }
    25. // 注册singelfd信号,为创建handler处理子进程终止信号
    26. InstallSignalFdHandler(&epoll);
    27. .....
    28. // 注册property_set_fd, 设置其他系统属性并开启系统属性服务
    29. StartPropertyService(&epoll);
    30. MountHandler mount_handler(&epoll);
    31. .......
    32. ActionManager& am = ActionManager::GetInstance();
    33. ServiceList& sm = ServiceList::GetInstance();
    34. //解析init.rc 等文件,建立rc文件的action,service,启动其他进程。
    35. LoadBootScripts(am, sm);
    36. .....
    37. am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
    38. //rc文件中触发器为 on earyly-init 语句
    39. am.QueueEventTrigger("early-init");
    40. // 等待冷插拔设备初始化完成
    41. am.QueueBuiltinAction(wait_for_coldboot_done_action,"wait_for_coldboot_done");
    42. // so that we can start queuing up actions that require stuff from /dev.
    43. am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
    44. am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
    45. am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
    46. // 设备组合键初始化操作
    47. Keychords keychords;
    48. am.QueueBuiltinAction(
    49. [&epoll, &keychords](const BuiltinArguments& args) -> Result {
    50. for (const auto& svc : ServiceList::GetInstance()) {
    51. keychords.Register(svc->keycodes());
    52. }
    53. keychords.Start(&epoll, HandleKeychord);
    54. return Success();
    55. },
    56. "KeychordInit");
    57. am.QueueBuiltinAction(console_init_action, "console_init");
    58. // 开始触发rc文件中为 on init 的语句
    59. am.QueueEventTrigger("init");
    60. // Starting the BoringSSL self test, for NIAP certification compliance.
    61. am.QueueBuiltinAction(StartBoringSslSelfTest, "StartBoringSslSelfTest");
    62. // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
    63. // wasn't ready immediately after wait_for_coldboot_done
    64. am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
    65. // Initialize binder before bringing up other system services
    66. am.QueueBuiltinAction(InitBinder, "InitBinder");
    67. //不要在充电器模式下挂载文件系统或启动核心系统服务。.
    68. std::string bootmode = GetProperty("ro.bootmode", "");
    69. if (bootmode == "charger") {
    70. am.QueueEventTrigger("charger");
    71. } else {
    72. am.QueueEventTrigger("late-init");
    73. }
    74. // 根据属性的当前状态运行所有属性触发器。.
    75. am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
    76. while (true) {
    77. //进入死循环s.
    78. auto epoll_timeout = std::optional{};
    79. if (do_shutdown && !shutting_down) {
    80. do_shutdown = false;
    81. if (HandlePowerctlMessage(shutdown_command)) {
    82. shutting_down = true;
    83. }
    84. }
    85. if (!(waiting_for_prop || Service::is_exec_service_running())) {
    86. am.ExecuteOneCommand();
    87. }
    88. if (!(waiting_for_prop || Service::is_exec_service_running())) {
    89. if (!shutting_down) {
    90. auto next_process_action_time = HandleProcessActions();
    91. // 如果有一个进程需要重新启动,请及时唤醒。
    92. if (next_process_action_time) {
    93. epoll_timeout = std::chrono::ceil(
    94. *next_process_action_time - boot_clock::now());
    95. if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
    96. }
    97. }
    98. // 如果还有更多工作要做,请立即醒来。
    99. if (am.HasMoreCommands()) epoll_timeout = 0ms;
    100. }
    101. // 这里一直等待循环事件 过来
    102. if (auto result = epoll.Wait(epoll_timeout); !result) {
    103. LOG(ERROR) << result.error();
    104. }
    105. }
    106. return 0;
    107. }

    其中最关键就是解析init.rc 文件,并且按照rc文件定义去启动服务,然后开启死循环,用于接受epoll事件  

    init.rc文件

    init.rc文件在 /system/core/rootdir/init.rc 

    1. import /init.environ.rc
    2. import /init.usb.rc
    3. import /init.${ro.hardware}.rc
    4. import /vendor/etc/init/hw/init.${ro.hardware}.rc
    5. import /init.usb.configfs.rc
    6. import /init.${ro.zygote}.rc

    zygote服务启动

    Zygote是由init进程通过解析init.zygote.rc文件而创建

    我们可以看到/system/core/rootdir/下有4个init.zygote.rc文件,通过ro.zygote配置得值去读取对应配置文件,这里以init.zygote64.rc  为例子 

    1. service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    2. class main
    3. priority -20
    4. user root
    5. group root readproc reserved_disk
    6. socket zygote stream 660 root system
    7. socket usap_pool_primary stream 660 root system
    8. onrestart write /sys/android_power/request_state wake
    9. onrestart write /sys/power/state on
    10. onrestart restart audioserver
    11. onrestart restart cameraserver
    12. onrestart restart media
    13. onrestart restart netd
    14. onrestart restart wificond
    15. writepid /dev/cpuset/foreground/tasks

    对应的可执行程序是app_process64 , 对应的源文件是/frameworks/base/cmds/app_process/app_main.cpp

    zygote启动过程如下: 

    1.创建了AppRuntime,并且调用了start方法。 

    2. AndroidRuntime调用了startVm创建了虚拟机,调用startReg注册JNI函数。 

    3.通过JNI调用ZygoteInit.main 进入Java  。

    4. 建立socket通道,zygote作为通讯服务端,用于响应客户端请求。 

    5. 预加载通用类,drawable,color资源,共享库等,用于提高app启动效率。 

    6. forksytem_server进程,上层java framework的运行载体。 

    参考文章:Android系统启动-zygote篇 - Gityuan博客 | 袁辉辉的技术博客袁辉辉, Gityuan, Android博客, Android源码, Flutter博客,Flutter源码http://gityuan.com/2016/02/13/android-zygote/

  • 相关阅读:
    Docker(三)、Dockerfile探究
    java 两个list比较,删除相同的元素
    幽默逻辑树
    ​@Cacheable 注解​
    Linux 网络编程
    【课设资源分享】基于jsp的俱乐部会员系统
    百度智能云数字人凭什么领跑中国AI数字人?
    读书笔记:Effective C++ 2.0 版,条款6(析构时delete)、7(内存不足)
    【精讲】mustache表达式写法、vue常用指令、v-bind多种绑定事件、技能提升
    通过IDEA打jar包
  • 原文地址:https://blog.csdn.net/Liang123l/article/details/131577647