Android 系統啓動

1、init進程啓動

init 進程是Android系統的第一個進程,很多重要職責,例如創建Zygote和屬性服務等。 init位於路勁system、core/init.

1.1引入init進程

1.啓動電源以及系統啓動
2.引導程序Bootloader
3.linux內核啓動
4.init進程啓動

1.2引入init進程

在main函數中system/core/init/init.cpp
int main(int argc, char** argv) {

//對屬性服務進行初始化
property_init(); //1

//用於設置子進程信號處理函數,如果子進程(zogete進程)異常退出,init進程會調用該函數中設定的信號處理函數來處理
signal_handler_init();//2

//啓動屬性服務
start_property-service();//3

//解析init.rc配置文件
parser.ParseConfig(“init.rc”);//4

//重啓死去的進程
restart_processes();//5
}
註釋2是爲了防止殭屍進程
父進程不知道子進程終止,但是此時系統進程表中還爲它保留了一定的信息,子進程爲殭屍進程。 進程表資源有限。

1.3init.rc

init.rc是一個配置文件,內部由Android初始化語言編寫(Android Init Language)編寫的腳本,它主要包含五種類型語句:
Action、Commands、Services、Options和Import。init.rc的配置代碼如下所示。
system/core/rootdir/init.rc

on init
    sysclktz 0
    # Mix device-specific information into the entropy pool
    copy /proc/cmdline /dev/urandom
    copy /default.prop /dev/urandom
...

on boot
    # basic network init
    ifup lo
    hostname localhost
    domainname localdomain
    # set RLIMIT_NICE to allow priorities from 19 to -20
    setrlimit 13 40 40
...

1.4 解析Service類型語句

init.rc中的Action星語句是ActionParser來進行解析,而Service由ServiceParser來進行解析。解析service,會用到兩個函數,一個是ParseSection,它會解析service的rc文件,比如上文講到的init.zygote64.rc,ParseSection函數主要用來搭建service的架子。另一個是ParseLineSection,用於解析子項。

1.5 init啓動zygote

Start方法
bool Service::Start() {
...
  pid_t pid = fork();//1.fork函數創建子進程
    if (pid == 0) {//2運行在子進程中
        umask(077);
        ...
        //3.通過execve執行程序
        if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) {
            ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno));
        }

        _exit(127);
    }

走到1處,子進程還沒被啓動。frok創建子進程,pid=0 說明在子線程中運行。3處service子進程就會被啓動,進入到service的main函數中。
frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
  ...
  if (zygote) {
      runtime.start("com.android.internal.os.ZygoteInit", args, zygote);//1
  } else if (className) {
      runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
  } else {
      fprintf(stderr, "Error: no class name or --zygote supplied.\n");
      app_usage();
      LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
      return 10;
  }
}

1處的代碼可以得知調用runtime(AppRuntime)的start來啓動zygote。

1.6 屬性服務

屬性服務初始化與啓動

ystem/core/init/property_service.cpp

void property_init() {
    if (__system_property_area_init()) {
        ERROR("Failed to initialize property area\n");
        exit(1);
    }
}
void start_property_service() {
    property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                    0666, 0, 0, NULL);//1
    if (property_set_fd == -1) {
        ERROR("start_property_service socket creation failed: %s\n", strerror(errno));
        exit(1);
    }
    listen(property_set_fd, 8);//2
    register_epoll_handler(property_set_fd, handle_property_set_fd);//3
}

註釋1處用來創建非阻塞的socket。註釋2處調用listen函數對property_set_fd進行監聽,這樣創建的socket就成爲了server,也就是屬性服務;listen函數的第二個參數設置8意味着屬性服務最多可以同時爲8個試圖設置屬性的用戶提供服務。註釋3處的代碼將property_set_fd放入了epoll句柄中,用epoll來監聽property_set_fd:當property_set_fd中有數據到來時,init進程將用handle_property_set_fd函數進行處理。
在linux新的內核中,epoll用來替換select,epoll最大的好處在於它不會隨着監聽fd數目的增長而降低效率。因爲內核中的select實現是採用輪詢來處理的,輪詢的fd數目越多,自然耗時越多。

屬性服務處理請求

會調用handle_property_set_fd函數進行處理:
system/core/init/property_service.cpp

static void handle_property_set_fd()
{  
...
handler_property_set(socket,prop_value,pro_value,true);//1
}

8.0在7.0做了進一步的判斷,普通屬性和控制屬性。

init進程總結

init進程主要做了三件事:
1.創建和掛載啓動所需的文件目錄
2.初始化和啓動屬性服務
3.解析init.rc配置文件並啓動zygote進程、

2、zygote進程啓動

1.Zygote簡介

在Android系統中,DVM(Dalvik虛擬機)和ART、應用程序進程以及運行系統的關鍵服務的SystemServer進程都是由Zygote進程來創建的,我們也將它稱爲孵化器。它通過fork
(複製進程)的形式來創建應用程序進程和SystemServer進程,由於Zygote進程在啓動時會創建DVM或者ART,因此通過fork而創建的應用程序進程和SystemServer進程可以在內部獲取一個DVM的實例拷貝。
啓動流程啓動流程

2、Zygote進程總結

Zygote進程共做了如下幾件事:
1.創建AppRuntime並調用其start方法,啓動Zygote進程。
2.創建DVM併爲DVM註冊JNI.
3.通過JNI調用ZygoteInit的main函數進入Zygote的Java框架層。
4.通過registerZygoteSocket函數創建服務端Socket,並通過runSelectLoop函數等待ActivityManagerService的請求來創建新的應用程序進程。
5.啓動SystemServer進程。

3 SyetemServer進程啓動過程

1.Zygote啓動SyetemServer進程

在這裏插入圖片描述
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

           // 關閉 zygote進程創建的socket 該進程對systemserver沒用
           zygoteServer.closeServerSocket();
           handleSystemServerProcess(parsedArgs);

handleSystemServerProcess函數的代碼:

 ClassLoader cl = null;
          if (systemServerClasspath != null) {
              cl = createSystemServerClassLoader(systemServerClasspath,
                                                 parsedArgs.targetSdkVersion);
              Thread.currentThread().setContextClassLoader(cl);
          }
          RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//2 

2處調用RuntimeInit的zygoteInit函數
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

 nativeZygoteInit();//1啓動binder線程池
applicationInit(targetSdkVersion, argv, classLoader);//2進入systemServer的main方法

invokeStaticMain

 private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

通過反射返回的cl爲SystemServer類。找到SystemServer中的main函數。將找到的main函數傳入到MethodAndArgsCaller異常中並拋出該異常。截獲MethodAndArgsCaller異常的代碼在ZygoteInit.java的main函數中
rameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
     ...
          closeServerSocket();
      } catch (MethodAndArgsCaller caller) {
          caller.run();//1
      } catch (RuntimeException ex) {
          Log.e(TAG, "Zygote died with exception", ex);
          closeServerSocket();
          throw ex;
      }
  }

在註釋1處調用了MethodAndArgsCaller的run函數:

   public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
         ...
        }
    }
}

2 解析SyetemServer進程

SystemServer的main函數:
frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
       new SystemServer().run();
   }

main函數中只調用了SystemServer的run函數,如下所示。

private void run() {
       ...
           System.loadLibrary("android_servers");//1
       ...
           mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
           LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
       ...    
        try {
           Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
           startBootstrapServices();//3
           startCoreServices();//4
           startOtherServices();//5
       } catch (Throwable ex) {
           Slog.e("System", "******************************************");
           Slog.e("System", "************ Failure starting system services", ex);
           throw ex;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
       ...
   }

3.總結SyetemServer進程

SyetemServer在啓動時做了如下工作:
1.啓動Binder線程池,這樣就可以與其他進程進行通信。
2.創建SystemServiceManager用於對系統的服務進行創建、啓動和生命週期管理。
3.啓動各種系統服務。

4 Launcher啓動過程與系統啓動流程

1.Launcher概述

launcher通俗的就是Android的系統的桌面。作用:
1、作爲Android系統的啓動器,用於啓動應用程序
2、作爲系統的桌面,用於顯示和管理應用程序的快捷圖標或者其他桌面組件

2.Launcher啓動流程

在這裏插入圖片描述
在systemServer 中startOtherServices函數,會調用ActivityManagerService的systemReady函數。
systemReady函數中調用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked函數:

3.Launcher中應用圖標顯示流程

Launcher的onCreate函數如下所示。
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

      @Override
    protected void onCreate(Bundle savedInstanceState) {
       ...
        LauncherAppState app = LauncherAppState.getInstance();//1 獲取實例
        mDeviceProfile = getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_LANDSCAPE ?
                app.getInvariantDeviceProfile().landscapeProfile
                : app.getInvariantDeviceProfile().portraitProfile;

        mSharedPrefs = Utilities.getPrefs(this);
        mIsSafeModeEnabled = getPackageManager().isSafeMode();
        mModel = app.setLauncher(this);//2
        ....
        if (!mRestoring) {
            if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE) {
                mModel.startLoader(PagedView.INVALID_RESTORE_PAGE);//3
            } else {
                mModel.startLoader(mWorkspace.getRestorePage());
            }
        }
...
    }

setluncher 處會調用LauncherModel的initialize函數:
在initialize函數中會將Callbacks,也就是傳入的Launcher 封裝成一個弱引用對象。因此我們得知mCallbacks變量指的就是封裝成弱引用對象的Launcher,這個mCallbacks後文會用到它。
再回到Launcher的onCreate函數,在註釋2處調用了LauncherModel的startLoader函數…

5.Android系統啓動流程

1.啓動電源以及系統啓動
當電源按下時引導芯片代碼開始從預定義的地方(固化在ROM)開始執行。加載引導程序Bootloader到RAM,然後執行。
2.引導程序BootLoader
引導程序BootLoader是在Android操作系統開始運行前的一個小程序,它的主要作用是把系統OS拉起來並運行。
3.Linux內核啓動
內核啓動時,設置緩存、被保護存儲器、計劃列表、加載驅動。當內核完成系統設置,它首先在系統文件中尋找init.rc文件,並啓動init進程。
4.init進程啓動
初始化和啓動屬性服務,並且啓動Zygote進程。
5.Zygote進程啓動
創建JavaVM併爲JavaVM註冊JNI,創建服務端Socket,啓動SystemServer進程。
6.SystemServer進程啓動
啓動Binder線程池和SystemServiceManager,並且啓動各種系統服務。
7.Launcher啓動
被SystemServer進程啓動的ActivityManagerService會啓動Launcher,Launcher啓動後會將已安裝應用的快捷圖標顯示到界面上。
在這裏插入圖片描述

發佈了17 篇原創文章 · 獲贊 10 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章