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