Android启动流程

安卓的启动流程

安卓的启动流程大致分为几个阶段。
1、BootRom:启动电源以及系统启动。
当电源按下时,引导芯片代码从预定义的地方(固化在ROM中)开始执行。加载引导程序BootLoader到RAM,然后执行。
2、引导程序Bootloader
引导程序BootLoader是在android操作系统开始运行前的一个小程序,他的主要作用是把系统OS拉起来并运行。
3、Linux kernel启动
当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并启动init进程。
4、init进程启动
初始化和启动属性服务,并且启动Zygote进程。
5、Zygote进程启动
创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。
6、systemserver进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
7、Launcher进程启动
被SystemServer进程启动的AMS会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
下面介绍安卓世界的启动流程即从init进程开始讲起。

init进程的启动

首先Bootloader引导程序启动完Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统,同时会加载用户级别的第一个进程init。启动该进程首先进入到system/core/init/目录下的main.cpp文件中,执行main方法。

51  int main(int argc, char** argv) {
52  #if __has_feature(address_sanitizer)
53      __asan_set_error_report_callback(AsanReportCallback);
54  #endif
55      // Boost prio which will be restored later
56      setpriority(PRIO_PROCESS, 0, -20);
57      if (!strcmp(basename(argv[0]), "ueventd")) {
58          return ueventd_main(argc, argv);
59      }
60  
61      if (argc > 1) {
62          if (!strcmp(argv[1], "subcontext")) {
63              android::base::InitLogging(argv, &android::base::KernelLogger);
64              const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
65  
66              return SubcontextMain(argc, argv, &function_map);
67          }
68  
69          if (!strcmp(argv[1], "selinux_setup")) {
70              return SetupSelinux(argv);
71          }
72  
73          if (!strcmp(argv[1], "second_stage")) {
74              return SecondStageMain(argc, argv);
75          }
76      }
77  
78      return FirstStageMain(argc, argv);
79  }
80  

FirstStageMain

可以在kernel中看到, 启动时并没有带任何参数,所在最先执行的就是FirstStageMain。这个函数主要功能就是创建目录、挂载分区等,最后进入第二次运行init,可以看到这次是带了selinux_setup参数;FirstStageMain函数实现在:system/core/init/first_stage_init.cpp。

int FirstStageMain(int argc, char** argv) {
...
353      if (!DoFirstStageMount(!created_devices)) {
354          LOG(FATAL) << "Failed to mount required partitions early ...";
355      }
...
372      const char* path = "/system/bin/init";
373      const char* args[] = {path, "selinux_setup", nullptr};
374      auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
375      dup2(fd, STDOUT_FILENO);
376      dup2(fd, STDERR_FILENO);
377      close(fd);
378      execv(path, const_cast<char**>(args));
379  
380      // execv() only returns if an error happened, in which case we
381      // panic and never fall through this conditional.
382      PLOG(FATAL) << "execv(\"" << path << "\") failed";

SetupSelinux

我们根据上面main函数的代码,参数为selinux_setup的时候,执行SetupSelinux函数,
第二步:进入SetupSelinux(argv),这个函数实现在system/core/init/selinux.cpp中。主要就是启动SElinux, 然后现再成功的进入下一步,根据参数可以看到, 接下来进入SecondStageMain

714  int SetupSelinux(char** argv) {
724      MountMissingSystemPartitions();
725  
726      SelinuxSetupKernelLogging();
727  
728      LOG(INFO) << "Opening SELinux policy";
729  
730      // Read the policy before potentially killing snapuserd.
731      std::string policy;
732      ReadPolicy(&policy);
...
742      LoadSelinuxPolicy(policy);
762      const char* path = "/system/bin/init";
763      const char* args[] = {path, "second_stage", nullptr};
764      execv(path, const_cast<char**>(args));
765   

SecondStageMain

函数实现是在system/core/init/init.cpp中

728  int SecondStageMain(int argc, char** argv) {
 PropertyInit();
 ...
 800      // Now set up SELinux for second stage.
801      SelinuxSetupKernelLogging();
802      SelabelInitialize();
803      SelinuxRestoreContext();
...
StartPropertyService(&property_fd);
...
837      ActionManager& am = ActionManager::GetInstance();
838      ServiceList& sm = ServiceList::GetInstance();
839  
840      LoadBootScripts(am, sm);
...
am.QueueEventTrigger("early-init");
...
      am.QueueEventTrigger("init");
  
      // Don't mount filesystems or start core system services in charger mode.
      std::string bootmode = GetProperty("ro.bootmode", "");
            if (bootmode == "charger") {
          am.QueueEventTrigger("charger");
      } else {
          am.QueueEventTrigger("late-init");
      }

可以该阶段主要做的事情是初始化property系统,解析init.rc。然后再执行early init action,执行init action, 执行 early-boot and boot actions。
其中/init.rc是主要的.rc文件,由init可执行文件在开始执行时加载。它负责系统的初始设置。
在加载主目录/init.rc后,init立即加载包含在/{system,vendor,odm}/etc/init/目录中的所有文件。

303  static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
304      Parser parser = CreateParser(action_manager, service_list);
305  
306      std::string bootscript = GetProperty("ro.boot.init_rc", "");
307      if (bootscript.empty()) {
308          parser.ParseConfig("/system/etc/init/hw/init.rc");
309          if (!parser.ParseConfig("/system/etc/init")) {
310              late_import_paths.emplace_back("/system/etc/init");
311          }
312          // late_import is available only in Q and earlier release. As we don't
313          // have system_ext in those versions, skip late_import for system_ext.
314          parser.ParseConfig("/system_ext/etc/init");
315          if (!parser.ParseConfig("/vendor/etc/init")) {
316              late_import_paths.emplace_back("/vendor/etc/init");
317          }
318          if (!parser.ParseConfig("/odm/etc/init")) {
319              late_import_paths.emplace_back("/odm/etc/init");
320          }
321          if (!parser.ParseConfig("/product/etc/init")) {
322              late_import_paths.emplace_back("/product/etc/init");
323          }
324      } else {
325          parser.ParseConfig(bootscript);
326      }
327  }
328  

我们先看init.rc文件的具体内容。

7 import /init.environ.rc
8 import /system/etc/init/hw/init.usb.rc
9 import /init.${ro.hardware}.rc
10 import /vendor/etc/init/hw/init.${ro.hardware}.rc
11 import /system/etc/init/hw/init.usb.configfs.rc
12 import /system/etc/init/hw/init.${ro.zygote}.rc
on early-init
...
119 on init
...
418     # This allows the ledtrig-transient properties to be created here so
419     # that they can be chown'd to system:system later on boot
420     write /sys/class/leds/vibrator/trigger "transient"
421 
422     # This is used by Bionic to select optimized routines.
423     write /dev/cpu_variant:${ro.bionic.arch} ${ro.bionic.cpu_variant}
424     chmod 0444 /dev/cpu_variant:${ro.bionic.arch}
425     write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant}
426     chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch}
427 
428     # Allow system processes to read / write power state.
429     chown system system /sys/power/state
430     chown system system /sys/power/wakeup_count
431     chmod 0660 /sys/power/state

438     # Start logd before any other services run to ensure we capture all of their logs.
439     start logd
440     # Start lmkd before any other services run so that it can register them
441     chown root system /sys/module/lowmemorykiller/parameters/adj
442     chmod 0664 /sys/module/lowmemorykiller/parameters/adj
443     chown root system /sys/module/lowmemorykiller/parameters/minfree
444     chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
445     start lmkd
446 
447     # Start essential services.
448     start servicemanager
449     start hwservicemanager
450     start vndservicemanager
...
467 # Mount filesystems and start core system services.
468 on late-init
469     trigger early-fs
...
475     trigger fs
476     trigger post-fs
...
495     # Now we can start zygote for devices with file based encryption
496     trigger zygote-start
497 
498     # Remove a file to wake up anything waiting for firmware.
499     trigger firmware_mounts_complete
500 
501     trigger early-boot
502     trigger boot

946 # It is recommended to put unnecessary data/ initialization from post-fs-data
947 # to start-zygote in device's init.rc to unblock zygote start.
948 on zygote-start && property:ro.crypto.state=unencrypted
949     wait_for_prop odsign.verification.done 1
950     # A/B update verifier that marks a successful boot.
951     exec_start update_verifier_nonencrypted
952     start statsd
953     start netd
954     start zygote
955     start zygote_secondary
956 
957 on zygote-start && property:ro.crypto.state=unsupported
958     wait_for_prop odsign.verification.done 1
959     # A/B update verifier that marks a successful boot.
960     exec_start update_verifier_nonencrypted
961     start statsd
962     start netd
963     start zygote
964     start zygote_secondary
965 
966 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
967     wait_for_prop odsign.verification.done 1
968     # A/B update verifier that marks a successful boot.
969     exec_start update_verifier_nonencrypted
970     start statsd
971     start netd
972     start zygote
973     start zygote_secondary

然后我们看是怎么解析init.rc文件的。给parse 变量进行赋值,创建了三个parser,分别是对service ,on,import进行parse。
首先*.rc 脚本中所有 service关键字定义的服务将会添加到 service_list 列表中。
*.rc 脚本中所有 on 关键开头的项将会被会添加到 action_list 列表中。

282  Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
283      Parser parser;
284  
285      parser.AddSectionParser("service", std::make_unique<ServiceParser>(
286                                                 &service_list, GetSubcontext(), std::nullopt));
287      parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
288      parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
289  
290      return parser;
291  }
35  void Parser::AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser) {
36      section_parsers_[name] = std::move(parser);
37  }

解析的关键函数是parseData函数,
next_token函数用就是寻找单词结束或者行结束标志,如果是单词结束标志就将单词push到args中,如果是行结束标志,则根据第一个单词来判断是否是一个section,section的标志只有三个"on",“service”,“import”,如果是"section",会根据关键字的不同会调用不同的 parser去解析(多态) 通过相应的ParseSection()函数来处理一个section,,action 使用 ActionParser,而 service 使用 ServiceParser 解析,该部分定义在LoadBootScrip()函数的第一行,parser.AddSectionParser()方法为parser的map成员section_parsers_创建了三个SectionParser,分别用来解析service,on,import的section;否则把这一行继续作为前“section”所属的行来处理
ParseSection()被用来解析一个新的section,ParseLineSection()被用来解析该section下的命令行

43  void Parser::ParseData(const std::string& filename, std::string* data) {
44      data->push_back('\n');
45      data->push_back('\0');
`...
73      for (;;) {
74          switch (next_token(&state)) {
75              case T_EOF:
76                  end_section();
77  
78                  for (const auto& [section_name, section_parser] : section_parsers_) {
79                      section_parser->EndFile();
80                  }
81  
82                  return;
83              case T_NEWLINE: {
84                  state.line++;
85                  if (args.empty()) break;
86                  // If we have a line matching a prefix we recognize, call its callback and unset any
87                  // current section parsers.  This is meant for /sys/ and /dev/ line entries for
88                  // uevent.
89                  auto line_callback = std::find_if(
90                      line_callbacks_.begin(), line_callbacks_.end(),
91                      [&args](const auto& c) { return android::base::StartsWith(args[0], c.first); });
92                  if (line_callback != line_callbacks_.end()) {
93                      end_section();
94  
95                      if (auto result = line_callback->second(std::move(args)); !result.ok()) {
96                          parse_error_count_++;
97                          LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
98                      }
99                  } else if (section_parsers_.count(args[0])) {
100                      end_section();
101                      section_parser = section_parsers_[args[0]].get();
102                      section_start_line = state.line;
103                      if (auto result =
104                                  section_parser->ParseSection(std::move(args), filename, state.line);
105                          !result.ok()) {
106                          parse_error_count_++;
107                          LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
108                          section_parser = nullptr;
109                          bad_section_found = true;
110                      }
111                  } else if (section_parser) {
112                      if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
113                          !result.ok()) {
114                          parse_error_count_++;
115                          LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
116                      }
117                  } else if (!bad_section_found) {
118                      parse_error_count_++;
119                      LOG(ERROR) << filename << ": " << state.line
120                                 << ": Invalid section keyword found";
121                  }
122                  args.clear();
123                  break;
124              }
125              case T_TEXT:
126                  args.emplace_back(state.text);
127                  break;
128          }
129      }
130  }

解析完了init.rc文件以后,调用am.QueueEventTrigger(‘init-early’)意为early-init时间已经到来,可以执行triggle只为early-init的action了。
init最终会进入了无限循环的监听状态,可以看到这里面一个核心函数就是 am.ExecuteOneCommand();之前说的QueueEventTrigger(“early-init”)把early-init加入到event_queue_的队列中,ExecuteOneCommand()一开始就遍历之前解析的action向量表。当一个 action 对象所有的 command 均执行完毕后,再执行下一个action。

zygote 启动

ini进程启动进程中,最关键的是启动zygote
我们在init.rc文件中可以看到出zygote的启动流程是,init.cpp中配置了late-init事件,然后在执行late-init事件的时候,触发了zygote-start事件,然后在zygote-start的时候,执行了start zygote以及start zygote_secondary启动了zygote进程。
zygote进程对应的bin文件是/system/bin/app_process64这个可执行文件,对应的源码路径为frameworks/base/cmds/app_process/app_main.cpp,所以会进到它的main函数中。
我们总结一下,zygote的主要行为是
创建虚拟机–startVM
注册JNI函数–startReg
通过JNI知道Java层的com.android.internal.os.ZygoteInit 类,调用main 函数,进入java 世界。
ZygoteInit.java的路径: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
该类中会调用ZygoteInit.startSystemServer去启动systemserver。

/frameworks/base/cmds/app_process/app_main.cpp

Zygote总结:
解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法
调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数
通过JNI方式调用ZygoteInit.main(),第一次进入Java世界
registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求
preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率
通过startSystemServer(),fork得力帮手system_server进程,也是Java Framework的运行载体(下面讲到system server再详细讲解)
调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作

systemserver进程的启动

system server进程是由zygote进程fork出来的,在上面的ZygoteInit.main方法中调用forksystemserver方法,新创建出来的system_server进程便进入handleSystemServerProcess()方法,然后执行ZygoteInit.zygoteInit通过反射获取SystemServer类的main方法参数

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
888      public static void main(String[] argv) {
...
975              if (startSystemServer) {
976                  Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
977  
978                  // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
979                  // child (system_server) process.
980                  if (r != null) {
981                      r.run();
982                      return;
983                  }
984              }
startBootstrapServices

启动系统启动所需的一小部分关键服务,这些服务具有复杂的相互依赖关系,所以会在此将他们全部初始化。

startCoreServices

启动一些在startBootstrapServices中没有依赖的一部分服务,具体服务如下:

SystemConfigService、BatteryService、UsageStatsService、CachedDeviceStateService、BinderCallsStatsService、LooperStatsService、RollbackManagerService、NativeTombstoneManagerService、BugreportManagerService、GpuService

startOtherServices

启动一些在startBootstrapServices和startCoreServices没有启动的服务,由于服务过多,在此只展示一些我们熟悉的服务,所有服务请通过阅读源码查看。

WindowManagerService、InputManagerService、VibratorManagerService、AlarmManagerService、BluetoothService、StorageManagerService、UiModeManagerService、StatusBarManagerService、VpnManagerService、NotificationManagerService、LocationManagerService、ConnectivityManager

最终也会启动SystemUI的Service。

SystemServer主要负责一下几部分内容:

启动相关的信息的存储。
设置Binder thread相关的配置。
构建ActivityThread以及系统上下文。
通过SystemServiceManager去启动系统中的各种Service。
使Main Looper进入循环,等待消息处理任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值