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  

 int main(int argc, char** argv) {
  #if __has_feature(address_sanitizer)
      __asan_set_error_report_callback(AsanReportCallback);
  #endif
  
      if (!strcmp(basename(argv[0]), "ueventd")) {
          return ueventd_main(argc, argv);
      }
  
      if (argc > 1) {
          if (!strcmp(argv[1], "subcontext")) {
              android::base::InitLogging(argv, &android::base::KernelLogger);
              const BuiltinFunctionMap function_map;
  
              return SubcontextMain(argc, argv, &function_map);
          }
  
          if (!strcmp(argv[1], "selinux_setup")) {
              return SetupSelinux(argv);
          }
  
          if (!strcmp(argv[1], "second_stage")) {
              return SecondStageMain(argc, argv);
          }
      }
  
      return FirstStageMain(argc, argv);
  }

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 

int FirstStageMain(int argc, char** argv) {
     
      .......  

      const char* path = "/system/bin/init";
      const char* args[] = {path, "selinux_setup", nullptr};
      execv(path, const_cast<char**>(args));
  
      // execv() only returns if an error happened, in which case we
      // panic and never fall through this conditional.
      PLOG(FATAL) << "execv(\"" << path << "\") failed";
  
      return 1;
 }

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

int SecondStageMain(int argc, char** argv) {
        ..... 

      // oom_scroe_adj 为-1000时候相当与关闭OOM机制。 范围 -1000 - 1000 
      if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
          LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
      }
  
      // 启用全局Seccomp 
      GlobalSeccomp();
 
      // 设置所有进程都可以访问的会话密钥环
       keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
  
      // 标记booting中 
      close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
  
         //初始化属性服务,指定文件读取属性
      property_init();

      ....... 
 
      // 为第二阶段设置 SELinux。
      SelinuxSetupKernelLogging();
      SelabelInitialize();
      SelinuxRestoreContext();
  
      // android封装好的Epoll开始初始化 
      Epoll epoll;
      if (auto result = epoll.Open(); !result) {
          PLOG(FATAL) << result.error();
      }
  
     // 注册singelfd信号,为创建handler处理子进程终止信号 
      InstallSignalFdHandler(&epoll);
  

      .....  

     // 注册property_set_fd, 设置其他系统属性并开启系统属性服务   
      StartPropertyService(&epoll);
      MountHandler mount_handler(&epoll);
   
     ....... 
  
  
      ActionManager& am = ActionManager::GetInstance();
      ServiceList& sm = ServiceList::GetInstance();
     //解析init.rc 等文件,建立rc文件的action,service,启动其他进程。 
      LoadBootScripts(am, sm);
  
      
      ..... 

      am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
  
      //rc文件中触发器为 on earyly-init 语句 
      am.QueueEventTrigger("early-init");
  
      // 等待冷插拔设备初始化完成 
    am.QueueBuiltinAction(wait_for_coldboot_done_action,"wait_for_coldboot_done");
      // so that we can start queuing up actions that require stuff from /dev.
      am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
      am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
      am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");

         // 设备组合键初始化操作 
      Keychords keychords;
      am.QueueBuiltinAction(
          [&epoll, &keychords](const BuiltinArguments& args) -> Result<Success> {
              for (const auto& svc : ServiceList::GetInstance()) {
                  keychords.Register(svc->keycodes());
              }
              keychords.Start(&epoll, HandleKeychord);
              return Success();
          },
          "KeychordInit");
      am.QueueBuiltinAction(console_init_action, "console_init");
  
      // 开始触发rc文件中为  on init 的语句  
      am.QueueEventTrigger("init");
  
      // Starting the BoringSSL self test, for NIAP certification compliance.
      am.QueueBuiltinAction(StartBoringSslSelfTest, "StartBoringSslSelfTest");
  
      // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
      // wasn't ready immediately after wait_for_coldboot_done
      am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
  
      // Initialize binder before bringing up other system services
      am.QueueBuiltinAction(InitBinder, "InitBinder");
  
      //不要在充电器模式下挂载文件系统或启动核心系统服务。.
      std::string bootmode = GetProperty("ro.bootmode", "");
      if (bootmode == "charger") {
          am.QueueEventTrigger("charger");
      } else {
          am.QueueEventTrigger("late-init");
      }   
     // 根据属性的当前状态运行所有属性触发器。.
      am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
  
      while (true) {
          //进入死循环s.
          auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
  
          if (do_shutdown && !shutting_down) {
              do_shutdown = false;
              if (HandlePowerctlMessage(shutdown_command)) {
                  shutting_down = true;
              }
          }
  
          if (!(waiting_for_prop || Service::is_exec_service_running())) {
              am.ExecuteOneCommand();
          }
          if (!(waiting_for_prop || Service::is_exec_service_running())) {
              if (!shutting_down) {
                  auto next_process_action_time = HandleProcessActions();
 
                 // 如果有一个进程需要重新启动,请及时唤醒。
                 if (next_process_action_time) {
                     epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
                              *next_process_action_time - boot_clock::now());
                      if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
                  }
             }
  
              // 如果还有更多工作要做,请立即醒来。
              if (am.HasMoreCommands()) epoll_timeout = 0ms;
         }
  
          // 这里一直等待循环事件 过来
          if (auto result = epoll.Wait(epoll_timeout); !result) {
             LOG(ERROR) << result.error();
         }
     }
  
     return 0;
 }

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

init.rc文件

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

 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

zygote服务启动

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

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


 service zygote /system/bin/app_process64 -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

对应的可执行程序是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/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/39511.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+Swingl实现拼图游戏

基于JavaSwingl实现拼图游戏 一、系统介绍二、效果展示三、其他系统实现四、获取源码 一、系统介绍 拼图游戏是一个简单的小程序&#xff0c;游戏规则如下&#xff1a;将一张大图分成9张小图&#xff0c;然后任意挑8张图&#xff0c;随意放在3行3列的矩阵中。 通过点击鼠标移动…

Maven 项目构建生命周期

Maven 项目构建生命周期 一句话: Maven 构建生命周期描述的是一次构建过程经历了多少个事件 生命周期的3 大阶段 clean 清理工作 default 核心工作&#xff0c;例如编译&#xff0c;测试&#xff0c;打包&#xff0c;部署等 site 产生报告&#xff0c;发布站点等 生命周期…

react和vue2/3父子组件的双向绑定(sync、emit、v-model)

目录 Vue .sync&#xff08;2.3.0&#xff09; $emit &#xff08;2.3后&#xff09; 自定义组件的 v-model 2.2.0 v-modelemits(3.0取消了.sync) React 父组件回调函数 相关基础 框架 MVC &#xff08;Model View Controller&#xff09;/MVP&#xff08;Model View…

RHCSA——Linux网络、磁盘及软件包管理

ZY目录 Linux操作系统讲解&#xff1a;一、网络管理1、NetworkManager1.1、nmtui界面&#xff1a;1.2、nmcli使用方法&#xff1a; 2、配置网络2.1、网络接口以及网络连接2.2、配置方法&#xff1a;2.3、ping命令&#xff1a;2.4、wget命令 二、磁盘管理2.1、分区得两种格式2.1…

日撸java三百行day77-79

文章目录 说明GUI1. GUI 总体布局2. GUI 代码理解2.1 对话框相关控件2.1.1 ApplicationShowdown.java&#xff08;关闭应用程序&#xff09;2.1.2 DialogCloser.java&#xff08;关闭对话框&#xff09;2.1.3 ErrorDialog.java&#xff08;显示错误信息&#xff09;2.1.4 HelpD…

day35-Postman/ajax

0目录 1.postman 2.ajax 1.Postman 1.1 定义&#xff1a;postman用于测试http协议接口&#xff0c;无论是开发还是测试人员 1.2 Servlet中的doGet&#xff08;&#xff09;/doPost…

idea 常用快捷键总结

IDEA常用快捷键总结 很多新手小白在使用IDEA进行代码编写的时候 对快捷键很感兴趣 这里泡泡给大家总结了一些常用的快捷键 希望能帮助到你 记得要收藏下来时常观看并且练习&#xff0c;才能熟练哦~ 1. 根据psvm或者main快速生成主函数 我们可以在类中输入psvm 或者main 然后I…

C# Winfrom将DataGridView数据导入Excel

1.项目添加Word和Excel的COM类型库引用 2.创建Excel工作表 //定义Excel操作对象Microsoft.Office.Interop.Excel.Application excelApp new Microsoft.Office.Interop.Excel.Application();//定义Excel工作表Microsoft.Office.Interop.Excel.Worksheet worksheet excelApp.Wo…

TCP的窗口控制和重发控制【TCP原理(笔记三)】

文章目录 利用窗口控制提高速度窗口控制与重发控制确认应答未能返回的情况某个报文段丢失的情况 控制流 利用窗口控制提高速度 TCP以1个段为单位&#xff0c;每发一个段进行一次确认应答的处理&#xff0c;如图。这样的传输方式有一个缺点。那就是&#xff0c;包的往返时间越长…

Centos使用docker部署nacos

Centos使用docker部署nacos 对于使用Docker部署Nacos&#xff0c;您可以按照以下步骤进行操作&#xff1a; 在您的服务器上安装Docker和Docker Compose。创建一个用于存储Nacos数据的目录&#xff0c;例如/path/to/nacos/data。创建一个docker-compose.yml文件&#xff0c;并…

心电前置放大电路制作与原理详细分析(附电路板实物图)

心电前置放大电路制作与原理详细分析(附电路板实物图) 实验目的实验结果实验电路图原理解释与计算实验测试过程实验参数测量实验洞洞板焊接实验目的 心电信号具有微弱、低频、和高阻抗等特性,极其容易受到干扰。为了实现心电信号的放大,前置放大器需要满足高输入阻抗、高共…

前端开发如何更好的避免样式冲突?级联层(CSS@layer)

目录 前言 一、什么是级联层 (Cascade Layers)&#xff1f; 1.1 级联层的官方定义 1.2 级联层为了解决什么问题&#xff1f; 二、理解级联层的前提 —— 级联 (cascade) 2.1 什么是级联&#xff1f; 2.2 当前级联的排序标准 2.3 级联起源&#xff08;Cascading Origins…

Spring Boot进阶(54):Windows 平台安装 MongoDB数据库 | 超级详细,建议收藏

1. 前言&#x1f525; Windows如何安装MongoDB数据库及使用呢&#xff1f;这将又会是干货满满的一期&#xff0c;全程无尿点不废话只抓重点教&#xff0c;具有非常好的学习效果&#xff0c;拿好小板凳准备就坐&#xff01;希望学习的过程中大家认真听好好学&#xff0c;学习的途…

第二章:在html中使用javascript

1、在html页面中插入js的主要方法就是使用<script>元素 2、html4.01为<script>定义了以下6个属性&#xff1a;【language已经废弃&#xff0c;其他5个属性都是可选的】 async 表示应该立即下载脚本&#xff0c;但不应该妨碍页面中的其他操作&#xff0c;比如下载…

中金:龙湖基本面稳健,股价超跌具备配置价值

恒大2.4万亿元的天量债务爆出后&#xff0c;让本就信心不足的房地产行业&#xff0c;越发雪上加霜&#xff0c;房企股价遭遇集体下挫&#xff0c;业内公认的万科、龙湖、保利、中海等“优等生”也不免被波及。多家证券机构提醒&#xff0c;行业预期降至冰点的情况下&#xff0c…

预付费电表收费系统

预付费电表收费系统是一种先进的电表管理系统&#xff0c;它能够帮助电力公司更加高效地管理电表收费&#xff0c;提高用电效率&#xff0c;降低能源浪费。本文将从以下几个方面介绍预付费电表收费系统的特点和优势。 一、预付费电表收费系统的原理 预付费电表收费系统是指用户…

京东自动化功能之商品信息监控是否有库存

这里有两个参数,分别是area和skuids area是地区编码,我这里统计了全国各个区县的area编码,用户可以根据实际地址进行构造skuids是商品的信息ID填写好这两个商品之后,会显示两种状态,判断有货或者无货状态,详情如下图所示 简单编写下python代码,比如我们的地址是北京市…

2023无监督摘要顶会论文合集

2023无监督摘要顶会论文合集 写在最前面ACL-2023Aspect-aware Unsupervised Extractive Opinion Summarization 面向的无监督意见摘要&#xff08;没找到&#xff09;Unsupervised Extractive Summarization of Emotion Triggers *情绪触发(原因)的 *无监督 *抽取式 摘要&#…

postgresql 内核源码分析 表锁relation lock的使用,session lock会话锁的应用场景,操作表不再困难

​专栏内容&#xff1a; postgresql内核源码分析 手写数据库toadb 并发编程 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 表锁介绍 当表打开&#xff0c;或者操作表时&#xff0c;都需要…

CDA数据分析系01 anaconda

简介 数据处理集成包&#xff0c;不局限于python 创建一个新的environment conda create --name python34 python3.4 激活一个environment activate python34 # for windows conda的package管理 类似pip&#xff0c;conda install xxxx 查看已安装的python包 conda list…