? ? Android系統(tǒng)是一款基于Linux的移動(dòng)操作系統(tǒng),那么Android是如何啟動(dòng)起來的呢?本文就詳細(xì)闡述Android系統(tǒng)的啟動(dòng)過程。
?????? 從內(nèi)核之上,我們首先應(yīng)該從文件系統(tǒng)的init開始,因?yàn)?init 是內(nèi)核進(jìn)入文件系統(tǒng)后第一個(gè)運(yùn)行的程序,通常我們可以在linux的命令行中指定內(nèi)核第一個(gè)調(diào)用誰,如果沒指定那么內(nèi)核將會(huì)到/sbin/、/bin/ 等目錄下查找默認(rèn)的init,如果沒有找到那么就報(bào)告出錯(cuò)。
?????? init.c位置:system/core/init/init.c。
?????? 在init.c的main函數(shù)里面完成以下步驟:
???????1、創(chuàng)建設(shè)備節(jié)點(diǎn)。
???????2、初始化log系統(tǒng)。
???????3、解析init.rc文件,解析函數(shù)在同一目錄的parser.c里面實(shí)現(xiàn)。
?????? 4、初始化屬性服務(wù)器,在同一目錄下的property_service.c里面實(shí)現(xiàn)。
???????。。。。
?????? 最后、進(jìn)入loop等待事件到來。
???????init.rc的解析過程
?????? init.rc是一個(gè)初始化腳本,路徑(不確定):device/renesas/emev/init.rc
?????? 在init.c的main函數(shù)里面,調(diào)用parser.c的parse_config_file("/init.rc");執(zhí)行解析過程。
???????先讀取文件內(nèi)容到data里面,再調(diào)用parse_config(fn, data);進(jìn)行解析。
?????? init.rc包含Android初始化語言的四大類聲明:行為類(Actions)、命令類(Commands)、服務(wù)類(Services)、選項(xiàng)類(Options), 解析完會(huì)形成兩個(gè)列表service_list 和action_list。
?????? 其中有一個(gè)很重要的服務(wù)就是zygote,在init.rc里面的片段:
Java代碼
service?zygote?/system/bin/app_process?-Xzygote?/system/bin?--zygote?--start-system-server ?? ????socket?zygote?stream?666?? ????onrestart?write?/sys/android_power/request_state?wake ?? ????onrestart?write?/sys/power/state?on ?? ????onrestart?restart?media?? ?????? 這是腳本中service的格式:
Java代碼
service?<name>?<pathname>?[?<argument>?]* ?? <option> ?? <option> ?? ...?? ???????zygote對(duì)應(yīng)的可執(zhí)行文件為app_process,android2.2中它的源代碼位置:framework/base/cmds/app_process。
???????app_main.cpp的main函數(shù),它先調(diào)用AndroidRuntime::addVmArguments將它的參數(shù)“-Xzygote /system/bin”傳給AndroidRuntime作為啟動(dòng)JavaVM用。接著如果定位余下的參數(shù),如果有"--zygote",執(zhí)行下面代碼,從參數(shù)可以知道,這時(shí)候要求啟動(dòng)start system server,并且將com.android.internal.os.ZygoteInit裝載至虛擬機(jī)。
C++代碼
ZygoteInit.java的main方法)。??? ?? ????????if?(0?==?strcmp("--zygote",?arg))?{??? ?? ????????????bool?startSystemServer?=?(i?<?argc)????? ?? ????????????????????strcmp(argv[i],?"--start-system-server")?==?0?:?false;??? ?? ????????????setArgv0(argv0,?"zygote");??? ?? ????????????set_process_name("zygote");??? ?? ????????????runtime.start("com.android.internal.os.ZygoteInit",??? ?? ????????????????startSystemServer);??? ?? ????????}???? ?????? 否則不啟動(dòng)system server:
C++代碼
set_process_name(argv0);??? ?? ?? ?? runtime.mClassName?=?arg;??? ?? ?? ?? runtime.mArgC?=?argc-i;??? ?? runtime.mArgV?=?argv+i;??? ?? ?? ?? ?? ?? LOGV("App?process?is?starting?with?pid=%d,?class=%s.\n",??? ?? ?????getpid(),?runtime.getClassName());??? ?? runtime.start();?? ???????runtime是AppRuntime對(duì)象,繼承自AndroidRuntime,在AndroitRuntime.app里的start()函數(shù)如下,默認(rèn)裝載的是RuntimeInit進(jìn)程,不啟動(dòng)system server。
C++代碼
void?AndroidRuntime::start()??? ?? {??? ?? ????start("com.android.internal.os.RuntimeInit",??? ?? ????????false? }??? ?????? 在AndroidRuntime.cpp的start方法內(nèi),先啟動(dòng)JAVA虛擬機(jī),在定位執(zhí)行className類的main方法(如果才存在的話)。
C++代碼
void?AndroidRuntime::start(const?char*?className,?const?bool?startSystemServer)??? ?? {??? ?? ????LOGD("\n>>>>>>>>>>>>>>?AndroidRuntime?START?<<<<<<<<<<<<<<\n");??? ?? ?? ?? ?? ?? ???? ????if?(startVm(&mJavaVM,?&env)?!=?0)??? ?? ????????goto?bail;??? ?? ?? ?? ?? ?? ????startClass?=?env->FindClass(slashClassName);??? ?? ????if?(startClass?==?NULL)?{??? ?? ????????LOGE("JavaVM?unable?to?locate?class?'%s'\n",?slashClassName);??? ?? ???????? ????}?else?{??? ?? ????????startMeth?=?env->GetStaticMethodID(startClass,?"main",??? ?? ????????????"([Ljava/lang/String;)V");??? ?? ????????if?(startMeth?==?NULL)?{??? ?? ????????????LOGE("JavaVM?unable?to?find?main()?in?'%s'\n",?className);??? ?? ???????????? ????????}?else?{??? ?? ????????????env->CallStaticVoidMethod(startClass,?startMeth,?strArray);??? ?? ????????}??? ?? ????}??? ?? }???? ?????? 先看怎么啟動(dòng)虛擬機(jī)的,在startVm方法內(nèi),先將一些系統(tǒng)參數(shù)選項(xiàng),包括虛擬機(jī)相關(guān)的屬性,保存到一個(gè)JavaVMOption的實(shí)例內(nèi),比如虛擬機(jī)的堆大小,是否check jni,JNI版本信息,最后將這些參數(shù)傳給JNI_CreateJavaVM,創(chuàng)建JAVA虛擬機(jī)實(shí)例。
C++代碼
jint?JNI_GetDefaultJavaVMInitArgs(void*);??? ?? jint?JNI_CreateJavaVM(JavaVM**,?JNIEnv**,?void*);??? ?? jint?JNI_GetCreatedJavaVMs(JavaVM**,?jsize,?jsize*);???? ?????? 在JNI_CreateJavaVM中,先檢查JNI的版本,為JavaVM,JNIEnv開辟空間,保存通用接口,最后解析傳進(jìn)來的參數(shù),最后調(diào)用dvmStartup啟動(dòng)虛擬機(jī)(有些傳給JNI_CreateJavaVM的參數(shù),也直接傳給了dvmStartup)。
?????? 這里的JNIEnv實(shí)際是JNIEnvExt強(qiáng)制轉(zhuǎn)換過來的,JNIEnvExt是JNIEnv結(jié)構(gòu)體的擴(kuò)展,JNIEnExt前端與JNIEnv完全對(duì)齊,都是JNI函數(shù)指針。相當(dāng)于JNIEnExt對(duì)JNIEnv進(jìn)行了賦值。
C++代碼
pEnv?=?(JNIEnvExt*)?dvmCreateJNIEnv(NULL);??? ?????? 在dvmStartup在Init.c定義,先調(diào)用setCommandLineDefaults進(jìn)行一些默認(rèn)的設(shè)置,比如虛擬機(jī)的默認(rèn)heap大小。
C++代碼
static?void?setCommandLineDefaults()??? ?? {??? ?? ????gDvm.heapSizeStart?=?2?*?1024?*?1024;??? ????gDvm.heapSizeMax?=?16?*?1024?*?1024;???? ????gDvm.stackSize?=?kDefaultStackSize;??? ?? }???? ?????? 然后調(diào)用dvmProcessOptions處理傳進(jìn)來的參數(shù),比如是否執(zhí)行zygote,最后,根據(jù)gDvm.zygote的值,是否申請(qǐng)一個(gè)新的堆,這個(gè)值在有參數(shù)-Xzygote置1。
C++代碼
if?(gDvm.zygote)?{??? ?? ????if?(!dvmInitZygote())??? ?? ????????goto?fail;??? ?? }?else?{??? ?? ????if?(!dvmInitAfterZygote())??? ?? ????????goto?fail;??? ?? }?? ?????? 到這里,虛擬機(jī)算是啟動(dòng)成功了。
???????回到AndroidRuntime.cpp的start方法,現(xiàn)在我們要啟動(dòng)ZygoteInit進(jìn)程,找到ZygoteInit的main方法,調(diào)用env->CallStaticVoidMethod(startClass, startMeth, strArray);去啟動(dòng)它。
?????? CallStaticVoidMethod在Jni.c里面有定義,但不是直接定義的,因此用CallStaticVoidMethod作為函數(shù)名直接查定義是查不到的,是這樣定義的:
?????? CALL_STATIC(void, Void, , , false);
?????? 再看CALL_STATIC的宏定義:
C++代碼
#define?CALL_STATIC(_ctype,?_jname,?_retfail,?_retok,?_isref)???????????????\?????? ????static?_ctype?CallStatic##_jname##Method(JNIEnv*?env,?jclass?jclazz,????\??? ?? ????????jmethodID?methodID,?...)????????????????????????????????????????????\??? ?? ????{???????????????????????????????????????????????????????????????????????\??? ?? ????????UNUSED_PARAMETER(jclazz);???????????????????????????????????????????\??? ?? ????????JNI_ENTER();????????????????????????????????????????????????????????\??? ?? ????????JValue?result;??????????????????????????????????????????????????????\??? ?? ????????va_list?args;???????????????????????????????????????????????????????\??? ?? ????????va_start(args,?methodID);???????????????????????????????????????????\??? ?? ????????dvmCallMethodV(_self,?(Method*)methodID,?NULL,?true,?&result,?args);\??? ?? ????????va_end(args);???????????????????????????????????????????????????????\??? ?? ????????if?(_isref?&&?!dvmCheckException(_self))????????????????????????????\??? ?? ????????????result.l?=?addLocalReference(env,?result.l);????????????????????\??? ?? ????????JNI_EXIT();?????????????????????????????????????????????????????????\??? ?? ????????return?_retok;??????????????????????????????????????????????????????\??? ?? ????}???????????????????????????????????????????????????????????????????????\??? ?? ????static?_ctype?CallStatic##_jname##MethodV(JNIEnv*?env,?jclass?jclazz,???\??? ?? ????????jmethodID?methodID,?va_list?args)???????????????????????????????????\??? ?? ????{???????????????????????????????????????????????????????????????????????\??? ?? ????????UNUSED_PARAMETER(jclazz);???????????????????????????????????????????\??? ?? ????????JNI_ENTER();????????????????????????????????????????????????????????\??? ?? ????????JValue?result;??????????????????????????????????????????????????????\??? ?? ????????dvmCallMethodV(_self,?(Method*)methodID,?NULL,?true,?&result,?args);\??? ?? ????????if?(_isref?&&?!dvmCheckException(_self))????????????????????????????\??? ?? ????????????result.l?=?addLocalReference(env,?result.l);????????????????????\??? ?? ????????JNI_EXIT();?????????????????????????????????????????????????????????\??? ?? ????????return?_retok;??????????????????????????????????????????????????????\??? ?? ????}???????????????????????????????????????????????????????????????????????\??? ?? ????static?_ctype?CallStatic##_jname##MethodA(JNIEnv*?env,?jclass?jclazz,???\??? ?? ????????jmethodID?methodID,?jvalue*?args)???????????????????????????????????\??? ?? ????{???????????????????????????????????????????????????????????????????????\??? ?? ????????UNUSED_PARAMETER(jclazz);???????????????????????????????????????????\??? ?? ????????JNI_ENTER();????????????????????????????????????????????????????????\??? ?? ????????JValue?result;??????????????????????????????????????????????????????\??? ?? ????????dvmCallMethodA(_self,?(Method*)methodID,?NULL,?true,?&result,?args);\??? ?? ????????if?(_isref?&&?!dvmCheckException(_self))????????????????????????????\??? ?? ????????????result.l?=?addLocalReference(env,?result.l);????????????????????\??? ?? ????????JNI_EXIT();?????????????????????????????????????????????????????????\??? ?? ????????return?_retok;??????????????????????????????????????????????????????\??? ?? ????}???? ?????? 因此CallStaticVoidMethod調(diào)用的是dvmCallMethodV方法,至于怎么樣再調(diào)用到ZygoteInit的main方法,有待研究,現(xiàn)在直接看ZygoteInit的main方法,它的參數(shù)是這樣定義的:
C++代碼
stringClass?=?env->FindClass("java/lang/String");??? ?? assert(stringClass?!=?NULL);??? ?? strArray?=?env->NewObjectArray(2,?stringClass,?NULL);??? ?? assert(strArray?!=?NULL);??? ?? classNameStr?=?env->NewStringUTF(className);??? ?? assert(classNameStr?!=?NULL);??? ?? env->SetObjectArrayElement(strArray,?0,?classNameStr);??? ?? startSystemServerStr?=?env->NewStringUTF(startSystemServer????? ?? ?????????????????????????????????????????????"true"?:?"false");??? ?? env->SetObjectArrayElement(strArray,?1,?startSystemServerStr);??? ?????? 申請(qǐng)一個(gè)String變量,給把類名作為第0個(gè)參數(shù),第二個(gè)參數(shù)是"ture"或"false",用來決定是否啟動(dòng)system service,在ZygoteInit的main方法會(huì)讀取這個(gè)參數(shù)。
C++代碼
if?(argv[1].equals("true"))?{??? ?? ????startSystemServer();??? ?? }?else?if?(!argv[1].equals("false"))?{??? ?? ????throw?new?RuntimeException(argv[0]?+?USAGE_STRING);??? ?? }?? ?????? 它讀取到第一個(gè)參數(shù)是"true",所以調(diào)用startSystemServer啟動(dòng)system server,在startSystemServer中,調(diào)用Zygote的forkSystemServer,fork出來的子進(jìn)程,就是system server了,調(diào)用事的參數(shù)如下:
C++代碼
String?args[]?=?{??? ?? ????"--setuid=1000",??? ?? ????"--setgid=1000",??? ?? ????"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",??? ?? ????"--capabilities=130104352,130104352",??? ?? ????"--runtime-init",??? ?? ????"--nice-name=system_server",??? ?? ????"com.android.server.SystemServer",??? ?? };?? ?????? 這些參數(shù)解析到一個(gè)ZygoteConnection.Arguments對(duì)象中。forkSystemServer方法實(shí)際上是JNI方法,在vm/native/dalvik_system_Zygote.c中有定義。
C++代碼
static?void?Dalvik_dalvik_system_Zygote_forkSystemServer(??? ?? ????????const?u4*?args,?JValue*?pResult)??? ?? {??? ?? ????pid_t?pid;??? ?? ????pid?=?forkAndSpecializeCommon(args);??? ?? ????if?(pid?>?0)?{??? ?? ????????int?status;??? ?? ?? ?? ?? ?? ????????LOGI("System?server?process?%d?has?been?created",?pid);??? ?? ????????gDvm.systemServerPid?=?pid;??? ?? ?? ?? ?? ?? ????????if?(waitpid(pid,?&status,?WNOHANG)?==?pid)?{??? ?? ????????????LOGE("System?server?process?%d?has?died.?Restarting?Zygote!",?pid);??? ?? ????????????kill(getpid(),?SIGKILL);??? ?? ????????}??? ?? ????}??? ?? ????RETURN_INT(pid);??? ?? }?? ?????? 具體的fork操作在forkAndSpecializeCommon里面進(jìn)行,父進(jìn)程檢查子進(jìn)程是否died。
?????? 在forkAndSpecializeCommon,先判斷是否zygote模式,是否剩余有足夠的heap空間,最后才執(zhí)行fork()系統(tǒng)調(diào)用。
?????? fork之后,父進(jìn)程不做操作,子進(jìn)程調(diào)用dvmInitAfterZygote去為自己申請(qǐng)堆空間。
?????? 子進(jìn)程返回到startSystemServer方法。
C++代碼
if?(pid?==?0)?{??? ?? ????handleSystemServerProcess(parsedArgs);??? ?? }??? ?????? 調(diào)用handleSystemServerProcess方法,在里面先設(shè)置uid的權(quán)限,再調(diào)用RuntimeInit.zygoteInit。
C++代碼
RuntimeInit.zygoteInit(parsedArgs.remainingArgs);??? ?? ???????在zygoteInit里面調(diào)用invokeStaticMain,invokeStaticMain先將com.android.server.Systemserver類的main方法取出,作為Method對(duì)象,然后和參數(shù)一起傳給ZygoteInit.MethodAndArgsCaller,MethodAndArgsCaller繼承自Runner,最終MethodAndArgsCaller調(diào)用Method.invode函數(shù)啟動(dòng)System Server。
總結(jié)
以上是生活随笔 為你收集整理的Android系统启动过程全解析 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。