Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android系統啟動過程全解析

Android系統啟動過程全解析

編輯:關於android開發

       Android系統是一款基於Linux的移動操作系統,那麼Android是如何啟動起來的呢?本文就詳細闡述Android系統的啟動過程。

       從內核之上,我們首先應該從文件系統的init開始,因為 init 是內核進入文件系統後第一個運行的程序,通常我們可以在linux的命令行中指定內核第一個調用誰,如果沒指定那麼內核將會到/sbin/、/bin/ 等目錄下查找默認的init,如果沒有找到那麼就報告出錯。

       init.c位置:system/core/init/init.c。

       在init.c的main函數裡面完成以下步驟:

       1、創建設備節點。

       2、初始化log系統。

       3、解析init.rc文件,解析函數在同一目錄的parser.c裡面實現。

       4、初始化屬性服務器,在同一目錄下的property_service.c裡面實現。

       。。。。

       最後、進入loop等待事件到來。

       init.rc的解析過程

       init.rc是一個初始化腳本,路徑(不確定):device/renesas/emev/init.rc

       在init.c的main函數裡面,調用parser.c的parse_config_file("/init.rc");執行解析過程。

       先讀取文件內容到data裡面,再調用parse_config(fn, data);進行解析。

       init.rc包含Android初始化語言的四大類聲明:行為類(Actions)、命令類(Commands)、服務類(Services)、選項類(Options),解析完會形成兩個列表service_list 和action_list。

       其中有一個很重要的服務就是zygote,在init.rc裡面的片段:

Java代碼
  1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server   
  2.     socket zygote stream 666  
  3.     onrestart write /sys/android_power/request_state wake   
  4.     onrestart write /sys/power/state on   
  5.     onrestart restart media  

       這是腳本中service的格式:

Java代碼
  1. service <name> <pathname> [ <argument> ]*   
  2. <option>   
  3. <option>   
  4. ...  

       zygote對應的可執行文件為app_process,android2.2中它的源代碼位置:framework/base/cmds/app_process。

       app_main.cpp的main函數,它先調用AndroidRuntime::addVmArguments將它的參數“-Xzygote /system/bin”傳給AndroidRuntime作為啟動JavaVM用。接著如果定位余下的參數,如果有"--zygote",執行下面代碼,從參數可以知道,這時候要求啟動start system server,並且將com.android.internal.os.ZygoteInit裝載至虛擬機。

C++代碼
  1. ZygoteInit.java的main方法)。      
  2.         if (0 == strcmp("--zygote", arg)) {      
  3.             bool startSystemServer = (i < argc) ?      
  4.                     strcmp(argv[i], "--start-system-server") == 0 : false;      
  5.             setArgv0(argv0, "zygote");      
  6.             set_process_name("zygote");      
  7.             runtime.start("com.android.internal.os.ZygoteInit",      
  8.                 startSystemServer);      
  9.         }    

       否則不啟動system server:

C++代碼
  1. set_process_name(argv0);      
  2.      
  3. runtime.mClassName = arg;      
  4.      
  5. // Remainder of args get passed to startup class main()      
  6. runtime.mArgC = argc-i;      
  7. runtime.mArgV = argv+i;      
  8.      
  9.      
  10. LOGV("App process is starting with pid=%d, class=%s.\n",      
  11.      getpid(), runtime.getClassName());      
  12. runtime.start();  

       runtime是AppRuntime對象,繼承自AndroidRuntime,在AndroitRuntime.app裡的start()函數如下,默認裝載的是RuntimeInit進程,不啟動system server。

C++代碼
  1. void AndroidRuntime::start()      
  2. {      
  3.     start("com.android.internal.os.RuntimeInit",      
  4.         false /* Don't start the system server */);      
  5. }   

       在AndroidRuntime.cpp的start方法內,先啟動JAVA虛擬機,在定位執行className類的main方法(如果才存在的話)。

C++代碼
  1. void AndroidRuntime::start(const char* className, const bool startSystemServer)      
  2. {      
  3.     LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");      
  4.      
  5.      
  6.     /* start the virtual machine */     
  7.     if (startVm(&mJavaVM, &env) != 0)      
  8.         goto bail;      
  9.      
  10.      
  11.     startClass = env->FindClass(slashClassName);      
  12.     if (startClass == NULL) {      
  13.         LOGE("JavaVM unable to locate class '%s'\n", slashClassName);      
  14.         /* keep going */     
  15.     } else {      
  16.         startMeth = env->GetStaticMethodID(startClass, "main",      
  17.             "([Ljava/lang/String;)V");      
  18.         if (startMeth == NULL) {      
  19.             LOGE("JavaVM unable to find main() in '%s'\n", className);      
  20.             /* keep going */     
  21.         } else {      
  22.             env->CallStaticVoidMethod(startClass, startMeth, strArray);      
  23.         }      
  24.     }      
  25. }    

       先看怎麼啟動虛擬機的,在startVm方法內,先將一些系統參數選項,包括虛擬機相關的屬性,保存到一個JavaVMOption的實例內,比如虛擬機的堆大小,是否check jni,JNI版本信息,最後將這些參數傳給JNI_CreateJavaVM,創建JAVA虛擬機實例。

C++代碼
  1. //JNI_CreateJavaVM在jni.h中有聲明,代碼位置:dalvik/libnativehelper/include/nativehelper/,在Jni.c中有定義      
  2. jint JNI_GetDefaultJavaVMInitArgs(void*);      
  3. jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);      
  4. jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);    

       在JNI_CreateJavaVM中,先檢查JNI的版本,為JavaVM,JNIEnv開辟空間,保存通用接口,最後解析傳進來的參數,最後調用dvmStartup啟動虛擬機(有些傳給JNI_CreateJavaVM的參數,也直接傳給了dvmStartup)。

       這裡的JNIEnv實際是JNIEnvExt強制轉換過來的,JNIEnvExt是JNIEnv結構體的擴展,JNIEnExt前端與JNIEnv完全對齊,都是JNI函數指針。相當於JNIEnExt對JNIEnv進行了賦值。

C++代碼
  1. pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);   

       在dvmStartup在Init.c定義,先調用setCommandLineDefaults進行一些默認的設置,比如虛擬機的默認heap大小。

C++代碼
  1. static void setCommandLineDefaults()      
  2. {      
  3.     gDvm.heapSizeStart = 2 * 1024 * 1024;   // Spec says 16MB; too big for us.      
  4.     gDvm.heapSizeMax = 16 * 1024 * 1024;    // Spec says 75% physical mem      
  5.     gDvm.stackSize = kDefaultStackSize;      
  6. }    

       然後調用dvmProcessOptions處理傳進來的參數,比如是否執行zygote,最後,根據gDvm.zygote的值,是否申請一個新的堆,這個值在有參數-Xzygote置1。

C++代碼
  1. if (gDvm.zygote) {      
  2.     if (!dvmInitZygote())      
  3.         goto fail;      
  4. } else {      
  5.     if (!dvmInitAfterZygote())      
  6.         goto fail;      
  7. }  

       到這裡,虛擬機算是啟動成功了。

       回到AndroidRuntime.cpp的start方法,現在我們要啟動ZygoteInit進程,找到ZygoteInit的main方法,調用env->CallStaticVoidMethod(startClass, startMeth, strArray);去啟動它。

       CallStaticVoidMethod在Jni.c裡面有定義,但不是直接定義的,因此用CallStaticVoidMethod作為函數名直接查定義是查不到的,是這樣定義的:

       CALL_STATIC(void, Void, , , false);

       再看CALL_STATIC的宏定義:

C++代碼
  1. #define CALL_STATIC(_ctype, _jname, _retfail, _retok, _isref)               \      
  2.     static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass jclazz,    \      
  3.         jmethodID methodID, ...)                                            \      
  4.     {                                                                       \      
  5.         UNUSED_PARAMETER(jclazz);                                           \      
  6.         JNI_ENTER();                                                        \      
  7.         JValue result;                                                      \      
  8.         va_list args;                                                       \      
  9.         va_start(args, methodID);                                           \      
  10.         dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\      
  11.         va_end(args);                                                       \      
  12.         if (_isref && !dvmCheckException(_self))                            \      
  13.             result.l = addLocalReference(env, result.l);                    \      
  14.         JNI_EXIT();                                                         \      
  15.         return _retok;                                                      \      
  16.     }                                                                       \      
  17.     static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass jclazz,   \      
  18.         jmethodID methodID, va_list args)                                   \      
  19.     {                                                                       \      
  20.         UNUSED_PARAMETER(jclazz);                                           \      
  21.         JNI_ENTER();                                                        \      
  22.         JValue result;                                                      \      
  23.         dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\      
  24.         if (_isref && !dvmCheckException(_self))                            \      
  25.             result.l = addLocalReference(env, result.l);                    \      
  26.         JNI_EXIT();                                                         \      
  27.         return _retok;                                                      \      
  28.     }                                                                       \      
  29.     static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass jclazz,   \      
  30.         jmethodID methodID, jvalue* args)                                   \      
  31.     {                                                                       \      
  32.         UNUSED_PARAMETER(jclazz);                                           \      
  33.         JNI_ENTER();                                                        \      
  34.         JValue result;                                                      \      
  35.         dvmCallMethodA(_self, (Method*)methodID, NULL, true, &result, args);\      
  36.         if (_isref && !dvmCheckException(_self))                            \      
  37.             result.l = addLocalReference(env, result.l);                    \      
  38.         JNI_EXIT();                                                         \      
  39.         return _retok;                                                      \      
  40.     }    

       因此CallStaticVoidMethod調用的是dvmCallMethodV方法,至於怎麼樣再調用到ZygoteInit的main方法,有待研究,現在直接看ZygoteInit的main方法,它的參數是這樣定義的:

C++代碼
  1. stringClass = env->FindClass("java/lang/String");      
  2. assert(stringClass != NULL);      
  3. strArray = env->NewObjectArray(2, stringClass, NULL);      
  4. assert(strArray != NULL);      
  5. classNameStr = env->NewStringUTF(className);      
  6. assert(classNameStr != NULL);      
  7. env->SetObjectArrayElement(strArray, 0, classNameStr);      
  8. startSystemServerStr = env->NewStringUTF(startSystemServer ?      
  9.                                              "true" : "false");      
  10. env->SetObjectArrayElement(strArray, 1, startSystemServerStr);   

       申請一個String變量,給把類名作為第0個參數,第二個參數是"ture"或"false",用來決定是否啟動system service,在ZygoteInit的main方法會讀取這個參數。

C++代碼
  1. if (argv[1].equals("true")) {      
  2.     startSystemServer();      
  3. } else if (!argv[1].equals("false")) {      
  4.     throw new RuntimeException(argv[0] + USAGE_STRING);      
  5. }  

       它讀取到第一個參數是"true",所以調用startSystemServer啟動system server,在startSystemServer中,調用Zygote的forkSystemServer,fork出來的子進程,就是system server了,調用事的參數如下:

C++代碼
  1. String args[] = {      
  2.     "--setuid=1000",      
  3.     "--setgid=1000",      
  4.     "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",      
  5.     "--capabilities=130104352,130104352",      
  6.     "--runtime-init",      
  7.     "--nice-name=system_server",      
  8.     "com.android.server.SystemServer",      
  9. };  

       這些參數解析到一個ZygoteConnection.Arguments對象中。forkSystemServer方法實際上是JNI方法,在vm/native/dalvik_system_Zygote.c中有定義。

C++代碼
  1. static void Dalvik_dalvik_system_Zygote_forkSystemServer(      
  2.         const u4* args, JValue* pResult)      
  3. {      
  4.     pid_t pid;      
  5.     pid = forkAndSpecializeCommon(args);      
  6.     if (pid > 0) {      
  7.         int status;      
  8.      
  9.      
  10.         LOGI("System server process %d has been created", pid);      
  11.         gDvm.systemServerPid = pid;      
  12.      
  13.      
  14.         if (waitpid(pid, &status, WNOHANG) == pid) {      
  15.             LOGE("System server process %d has died. Restarting Zygote!", pid);      
  16.             kill(getpid(), SIGKILL);      
  17.         }      
  18.     }      
  19.     RETURN_INT(pid);      
  20. }  

       具體的fork操作在forkAndSpecializeCommon裡面進行,父進程檢查子進程是否died。

       在forkAndSpecializeCommon,先判斷是否zygote模式,是否剩余有足夠的heap空間,最後才執行fork()系統調用。

       fork之後,父進程不做操作,子進程調用dvmInitAfterZygote去為自己申請堆空間。

       子進程返回到startSystemServer方法。

C++代碼
  1. /* For child process */     
  2. if (pid == 0) {      
  3.     handleSystemServerProcess(parsedArgs);      
  4. }   

       調用handleSystemServerProcess方法,在裡面先設置uid的權限,再調用RuntimeInit.zygoteInit。

C++代碼
  1. /*    
  2.  * Pass the remaining arguments to SystemServer.    
  3.  * "--nice-name=system_server com.android.server.SystemServer"    
  4.  */     
  5. RuntimeInit.zygoteInit(parsedArgs.remainingArgs);      
  6. /* should never reach here */    

       在zygoteInit裡面調用invokeStaticMain,invokeStaticMain先將com.android.server.Systemserver類的main方法取出,作為Method對象,然後和參數一起傳給ZygoteInit.MethodAndArgsCaller,MethodAndArgsCaller繼承自Runner,最終MethodAndArgsCaller調用Method.invode函數啟動System Server。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved