從內核之上,我們首先應該從文件系統的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裡面的片段:
- 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的格式
- service <name> <pathname> [ <argument> ]*
- <option>
- <option>
- ...
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裝載至虛擬機
- 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);
- }
否則不啟動system server:
- set_process_name(argv0);
-
- runtime.mClassName = arg;
-
- // Remainder of args get passed to startup class main()
- 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對象,繼承自AndroidRuntime,在AndroitRuntime.app裡的start()函數如下,默認裝載的是RuntimeInit進程,不啟動system server.
- void AndroidRuntime::start()
- {
- start("com.android.internal.os.RuntimeInit",
- false /* Don't start the system server */);
- }
在AndroidRuntime.cpp的start方法內,先啟動JAVA虛擬機,在定位執行className類的main方法(如果才存在的話)。
- void AndroidRuntime::start(const char* className, const bool startSystemServer)
- {
- LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
-
-
- /* start the virtual machine */
- if (startVm(&mJavaVM, &env) != 0)
- goto bail;
-
-
- startClass = env->FindClass(slashClassName);
- if (startClass == NULL) {
- LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
- /* keep going */
- } else {
- startMeth = env->GetStaticMethodID(startClass, "main",
- "([Ljava/lang/String;)V");
- if (startMeth == NULL) {
- LOGE("JavaVM unable to find main() in '%s'\n", className);
- /* keep going */
- } else {
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
- }
- }
- }
先看怎麼啟動虛擬機的,在startVm方法內,先將一些系統參數選項,包括虛擬機相關的屬性,保存到一個JavaVMOption的實例內,比如虛擬機的堆大小,是否check jni,JNI版本信息,最後將這些參數傳給JNI_CreateJavaVM,創建JAVA虛擬機實例
- JNI_CreateJavaVM在jni.h中有聲明,代碼位置:dalvik/libnativehelper/include/nativehelper/,在Jni.c中有定義
- jint JNI_GetDefaultJavaVMInitArgs(void*);
- jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
- jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);