Android系统启动1---AndroidInit进程


目录

1、Init进程概述

  1.1 Android启动流程

  1.2 直观感受

  1.3 Init进程职责

2、解析init.rc

  2.1  Android Init language

  2.2  解析init.rc

  2.3  循环触发Action

  2.4   解析、启动service(zygote)

3、属性服务

  3.1  获取属性(属性相当于Windows下的注册表)

  3.2  属性服务启动

  3.3   设置属性过程

4、服务守护进程

4.0 守护进程

  4.1  init.c 无限循环遍历service_list进行守护

  

1、Init进程概述

  • 1.1 Android启动流程
  • 1.2 直观感受
  • Init是Linux系统用户空间的第一个进程。也就是基于Linux内核的Android系统用户空间的第一个进程。
  • 代码路径:system/core/init/init.c
  • 1.3 Init进程职责
    • 解析property文件并初始化property。
    • 解析脚本init.rc,触发Action及启动Service。
    • 提供系统property服务管理及完成对应的触发事件。
    • 维护系统级Service。

2、解析init.rc

  • 2.1  Android Init language
    • The Android Init Language consists of four broad classes of statements:

      Action

      Commands

      Services

      Options

    • Init Language的关键字及相关关键字处理函数定义:

      system/core/init/keywords.h

      例如:

      KEYWORD(on,            SECTION, 0, 0)

      KEYWORD(service,     SECTION, 0, 0)

    • on <trigger>

        <command>

        <command>

        <command>  ...

      service <name> <pathname> [ <argument> ]*

        <option>

        <option>  ...

  • 2.2  解析init.rc
  • 2.3  循环触发Action
    • for(;;) {

      execute_one_command();

          restart_processes();

          ......

      }

      execute_one_command的关键逻辑:

      1.action_remove_queue_head函数获取action_queue链表中的第一个action节点
      2.通过action节点调用get_next_command函数获取它的下一个Command
      3.执行Command

      关键点,通过函数上层的for循环,首先获取Action节点,其次循环获取并执行Action节点下的Command,Command循环完成后,再获取下一个Action节点

  • 2.4   解析、启动service(zygote)
    • service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

          class main

          socket zygote stream 660 root system

          onrestart write /sys/android_power/request_state wake

          onrestart write /sys/power/state on

          onrestart restart media

          onrestart restart netd

3、属性服务

  • 3.1  获取属性(属性相当于Windows下的注册表)
    • 使用 adb shell getprop
  • 3.2  属性服务启动
    • Property服务启动入口:

      action_queue中的Action:property_service_init,对应的函数指针: property_service_init_action

    • 初始化调用过程:

      property_service_init_action-> start_property_service-> load_properties_from_file& create_socket& listen&set property_set_fd

    • 多路切换监听过程
       1 for(;;) {
       2 
       3       ......
       4 
       5       if (!property_set_fd_init && get_property_set_fd() > 0) {
       6 
       7           ufds[fd_count].fd = get_property_set_fd();
       8 
       9           ufds[fd_count].events = POLLIN;
      10 
      11           ufds[fd_count].revents = 0;
      12 
      13           fd_count++;
      14 
      15           property_set_fd_init = 1;
      16 
      17       }
      18 
      19       ......
      20 
      21       nr = poll(ufds, fd_count, timeout);
      22 
      23 }

       

  • 3.3   设置属性过程
    • 有些Action有属性条件的:

      on property:persist.service.adb.enable=1
             start adbd

      queue_property_triggers

      action_add_queue_tail

4、服务守护进程

  • 4.0 守护进程
    守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。Linux系统有很多守护进程,大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。
    由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能够突破这种限制,它从被执行开始运转,直到整个系统关闭时才退出。如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。(摘自百度百科)
  • 4.1  init.c 无限循环遍历service_list进行守护
    •  1 for(;;) {
       2 
       3         ...
       4     //restart_processes作用
       5     //循环获取service_list中的Service节点
       6     //调用service_for_each_flags函数,通过Service节点中的flags、 time_started判断是否启动该Service
       7     //调用service_start函数,fork子进程,创建Socket、执行启动Service等操作
       8 
       9         restart_processes();
      10 
      11         ...
      12 
      13         nr = poll(ufds, fd_count, timeout);
      14 
      15         if (nr <= 0)
      16 
      17             continue;
      18 
      19 
      20 
      21         for (i = 0; i < fd_count; i++) {
      22 
      23             if (ufds[i].revents & POLLIN) {
      24 
      25                 if (ufds[i].fd == get_property_set_fd())
      26 
      27                     handle_property_set_fd();
      28 
      29                 else if (ufds[i].fd == get_keychord_fd())
      30 
      31                     handle_keychord();
      32 
      33                 else if (ufds[i].fd == get_signal_fd())
      34 
      35                     handle_signal();
      36 
      37             }
      38 
      39         }
      40 
      41     }

       


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM