本文引用:http://blog.csdn.net/lizhiguo0532/article/details/7028910
------------------------------------------------------------------------------------------------------
Android的啟動過程是從進程init開始的,所以它是后續所有進程的祖先進程。
一、init進程
源碼位於system/core/init目錄。主要做了以下事情:
1. 重新設置子進程終止時信號SIGCHLD的處理函數。
act.sa_handler = sigchld_handler; //調用了wait函數等待子進程退出。
act.sa_flags = SA_NOCLDSTOP;
act.sa_mask = 0;
act.sa_restorer = NULL;
sigaction(SIGCHLD, &act, 0);
2. 將kernel啟動過程中建立好的文件系統框架mount到相應目錄。
mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
…
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
3. open_devnull_stdio(),將init進程的標准輸入、輸出、出錯設備設置為新建的設備節點/dev/__null__。
4. log_init(),創建並打開設備節點/dev/__kmsg__。
5. 讀取並解析rc配置文件。
5.1 先從文件/sys/class/BOOT/BOOT/boot/boot_mode讀出啟動方式:Factory Mode, '4';ATE Factory Mode, '6'。看是否是facatory模式。
5.2 如果是的話,需要讀取並解析兩個文件:init.factory.rc和init.rc。
5.3 如果是正常啟動,則暫時先讀取init.rc。
這里在讀取解析文件的時候,是以行為最小可執行單位在解析。關於書寫init.rc文件的初始化腳本語言的規則,可以上網查找。解析之后並不會馬上執行,而是在init進入服務循環之前統一根據其命令本身所帶的條件來執行。
6. 導入kernel的cmdline,也就是u-boot傳遞給kernel的參數,查看其中是否具有 androidboot.xxx(androidboot.mode、androidboot.hardware等)參數,如果有,將其保存在同名字的 xxx(mode、hardware)全局變量中。這里特別說明的是hardware這個參數,從kernel中導出一部分之后,又要從/proc /cpuinfo中導出一部分來組合成完整的hardware參數,因為后面接下來會讀取並解析以特定平台的rc文件。
7. 讀取特定平台相關的initrc文件,如:init.mt6516.rc。
需要注意的是:對於service,這里會給每個服務建立一個struct service的結構體,全部掛入鏈表service_list之中,在init最后才啟動。
8. 檢查解析出來的所有命令行當中是否有屬於early-init的,如果有,將其提出來加入到鏈表action_queue之中,馬上將其執行掉。
9. device_init()函數將會打開uevent的netlink socket,遍歷/sys/class、/sys/block、/sys/devices目錄,檢查各級目錄的uevent文件,處理在vold服務起 來之前由kernel所發出來的device add, remove等事件。
10. property_init(), 顧名思義,是屬性初始化。首先創建一個名字為system_properties的匿名共享內存區域,對並本init進程做mmap讀寫映射,其余共享它 的進程只有讀的權限。然后將這個prop_area結構體通過全局變量__system_property_area__傳遞給property services。
接着調用函數load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT)從/default.prop文件中加載編譯時生成的屬性。
11. 如果在root目錄下有initlogo.rle文件存在,這個是兩張android字樣的縷空圖片,將其讀入fb中顯示到LCD上。同時也要往串口上輸出" A N D R O I D "。如果圖片不存在,就沒有這兩項的輸出。
12. 設置相應的屬性:
property_set("ro.factorytest", "0")
property_set("ro.serialno", serialno[0] ? serialno : "");
property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
property_set("ro.baseband", baseband[0] ? baseband : "unknown");
property_set("ro.carrier", carrier[0] ? carrier : "unknown");
property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
property_set("ro.hardware", hardware);
snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
property_set("ro.revision", tmp);
13. 開始執行以init為trigger的命令行:
action_for_each_trigger("init", action_add_queue_tail);
drain_action_queue();
前面有執行過eraly-init的。
14. 啟動屬性服務:property_set_fd = start_property_service();
先讀取剩余三個文件中的屬性:/system/build.prop、/system/default.prop、/system /default.prop,然后用函數load_persistent_properties()加載persist.開始的屬性,這種屬性都是保存在 目錄/data/property下的以屬性名為文件名的中。
接下來創建一個名為property_service的socket接口(SOCK_STREAM),然后進入監聽狀態,等待屬性事件到來。
15. 創建一對socket,用來做信號方面的處理。
socketpair(AF_UNIX, SOCK_STREAM, 0, s),signal_fd = s[0],signal_recv_fd = s[1]。
16.執行eraly-boot和boot為trigger的命令
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
drain_action_queue();
17.執行init.rc中以property:開頭的屬性設置語句,同時使能屬性觸發方式。
queue_all_property_triggers();
drain_action_queue();
property_triggers_enabled = 1; // 可以執行那些以屬性為條件的init語句。
1. 接下來就是利用poll機制監聽前面創建的幾個fd的動態。
struct pollfd ufds[4];
…
ufds[0].fd = device_fd;
ufds[0].events = POLLIN;
ufds[1].fd = property_set_fd;
ufds[1].events = POLLIN;
ufds[2].fd = signal_recv_fd;
ufds[2].events = POLLIN;
for(;;) {
int nr, i, timeout = -1;
for (i = 0; i < fd_count; i++)
ufds[i].revents = 0;
drain_action_queue(); //執行action_queue鏈表中后來新出現的command。
restart_processes(); // 第一次啟動所有服務,也包括后來restart這些
服務。restart_service_if_needed() à service_start(svc, NULL) à fork()
…
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
if (ufds[2].revents == POLLIN) {
/* we got a SIGCHLD - reap and restart as needed */
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0))
;
continue;
}
if (ufds[0].revents == POLLIN)
handle_device_fd(device_fd); // Vold的netlink類型的socket
if (ufds[1].revents == POLLIN)
handle_property_set_fd(property_set_fd);//屬性服務的socket
if (ufds[3].revents == POLLIN)
handle_keychord(keychord_fd);
}
到這里init就進入了死循環中一直在監聽ufds中的4個文件描述符的動靜,如果有POLLIN的事件,就做相應的處理,所以init並沒有退出 或者進入idle,而是被當做一個服務在運行。第4個文件描述符是keychord_fd,暫時不清楚這個怎么用,不過通過它也可以啟動服務,可參考源 碼。
下面是init.rc的例子,見附件init.rc
二、init中啟動的各種服務
在init中啟動起來的服務按照init.rc中的先后順序,大致有:
console: start a shell,code path: system/bin/sh,其源碼中包含常用的shell命令,如ls,cd等。
adbd: start adb daemon,通常帶有disabled的選項,表明需要按名字啟動,code path:system/bin/adb。
servicemanager:這個服務管理着系統內所有binder services。code path: frameworks/base/cmds/servicemanager。
Vold: android 的udev,code path: system/vold。
Netd: start ntd daemon, code path: system/netd。
Debuggerd: start debug system, code path: system/core/debuggerd。
zygote: ['zaigəut]這是一個非常重要的服務,稍后詳解。start Android Java Runtime and start systemserver。code path:frameworks/base/cmds/app_process。
media: add AudioFlinger,AudioPolicyService,MediaPlayerService and CameraService to servicemanager,同時啟動管理binder通訊的機制,依靠這兩個類來完成binder機制在android中間層所體現的功 能:ProcessState 和IPCThreadState。Code path:frameworks/base/media/mediaserver。
bootanim: 開機動畫和鈴聲,code path:frameworks/base/cmds/bootanimation。
接下來就是關於modem的服務,如:ccci_fsd、ccci_mdinit、pppd_gprs、pppd、gsm0710muxd、 muxtestapp、sockcli、socksrv、muxreport、ril-daemon等,除了前面2個,后面的都帶有disabled的參 數,需要按名啟動。
Installd: start install package daemon, code path:
frameworks/base/cmds/installd。
后面還有很多關於其他硬件的服務,比如BT、WIFI等。
2.1 servicemanager
這個服務進程代碼比較簡單,功能也簡單,c實現的,用來管理系統中所有的binder service,不管是本地的c++實現的還是java語言實現的都需要這個進程來統一管理,最主要的管理就是,注冊添加服務,獲取服務。
這些binder服務在對外公開之前都必須將自身擁有的binder實體注冊到SMgr中,而其他進程如果需要使用binder service的功能,也必須先經過SMgr取得 binder service中的binder實體在SMgr中對應的引用號(binder的引用號和進程中文件描述符概念類似,有效范圍只限於本進程)。
#define BINDER_SERVICE_MANAGER ((void*) 0)
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
// 打開binder設備,mmap映射當前進程的binder接收緩沖區,返回一個binder_state結構體 。
if (binder_become_context_manager(bs)) {
// 通過這個函數將當前進程設置成服務管理進程MSgr,整個系統就這一個。
…
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
/*svcmgr_handler作為處理函數,所能完成的操作有:獲取service,查看service是否存在,添加service ,列出service清單。其中用的最多的就是獲取、添加。*/
return 0;
}
2.2 zygote
zygote服務進程也叫做孵化進程,在linux的用戶空間,進程app_process會做
一些zygote進程啟動的前期工作,如,啟動runtime運行時環境(實例),參數分解,設置startSystemServer標志,接着用 runtime.start()來執行zygote服務的代碼,其實說簡單點,就是zygote搶了app_process這個進程的軀殼,改了名字,將 后面的代碼換成zygote的main函數,這樣順利地過度到了zygote服務進程。這樣我們在控制台用ps看系統所有進程,就不會看到 app_process,取而代之的是zygote。
而前面runtime.start()這個函數實際上是類函數AndroidRuntime::start(),在
這個函數中,會新建並啟動一個虛擬機實例來執行com.android.internal.os.ZygoteInit這個包的main函數。這個 main函數中會fork一個子進程來啟動systemserver,父進程就作為真正的孵化進程存在了,每當系統要求執行一個 Android應用程序,Zygote就會收到socket消息FORK出一個子進程來執行該應用程序。因為Zygote進程是在系統啟動時產生的,它會 完成虛擬機的初始化,庫的加載,預置類庫的加載和初始化等操作,而在系統需要一個新的虛擬機實例時可以快速地制造出一個虛擬機出來。
每一個Android應用都運行在一個Dalvik虛擬機實例里,而每一個虛擬機實例都是一個獨立的進程空間。虛擬機的線程機制,內存分配和管 理,Mutex等等都是依賴底層linux實現的。所以android應用程序中創建了線程將會實際調用到linux的線程創建接口,和虛擬機所在進程共 享一個虛擬機實例對java代碼執行。
2.2.1 app_process
下面重點討論zygote服務,源碼位於frameworks/base/cmds/app_process。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
參數:/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
int main(int argc, const char* const argv[])
{
…
AppRuntime runtime; // 這里啟動runtime運行時環境(實例),AppRuntime是AndroidRuntime的子類,在創建這個對象的時候會依次調用基類和子類的構造函數。
const char *arg;
const char *argv0;
…
argv0 = argv[0];
// ignore argv[0]
argc--;
argv++;
/*
argc = 4;
argv[0] = “-Xzygote”;
argv[1] = “/system/bin”;
argv[2] = “--zygote”;
argv[3] = “–start-system-server”;
*/
int i = runtime.addVmArguments(argc, argv); // 找到參數中第一個不是以單個-開始的參數,這里很明顯是第二個參數:/system/bin
if (i < argc) {
runtime.mParentDir = argv[i++]; // 將命令目錄保存在mParentDir中,之后i = 2。
}
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) { // 通常這個分支是成立的
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
// startSystemServer = true ,這個bool變量決定着后面執行runtime.start時是否啟動systemserver。
setArgv0(argv0, "zygote");
set_process_name("zygote");
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
} else {
… // 只啟動AndroidRuntime
}
}else{
… // 錯誤處理
}
} // main()
2.2.2 AndroidRuntime
下面進一步分析
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
位於文件frameworks/base/core/jni/ AndroidRuntime.cpp,類定義於:
frameworks/base/include/android_runtime/AndroidRuntime.h
void AndroidRuntime::start(const char* className,
const bool startSystemServer){
LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
…
JNIEnv* env;
…
/* start the virtual machine , mJavaVM是類AndroidRuntime的私有變量,env該函數中局部變量 */
if (startVm(&mJavaVM, &env) != 0)
goto bail;
/* Register android functions.向剛剛新建的虛擬機注冊JNI本地接口。frameworks/base/core/jni/這個目錄下的所有jni接口。*/
if (startReg(env) < 0) {
…
goto bail;
}
//啟動虛擬機之前需要構造java形式的參數數組,如下:
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
stringClass = env->FindClass("java/lang/String");
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ?
"true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
/* strArray[0] = “com.android.internal.os.ZygoteInit”
strArry[1] = “true”*/
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/'; // 將包名換成路徑
startClass = env->FindClass(slashClassName); // 根據路徑找到這個包
// com.android.internal.os.ZygoteInit,這個類位於文件
// com/ndroid/nternal/os/ZygoteInit.java
if (startClass == NULL) {
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
/*這個參數決定了我們接下來執行的是zygoteInit.java的main函數。*/
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);
// 虛擬機啟動,將會調用到com.android.internal.os.ZygoteInit包的main函數。
…
}
}
LOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
LOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
LOGW("Warning: VM did not shut down cleanly\n");
bail:
free(slashClassName);
}
} // start()
2.2.3 ZygoteInit
下面進入com.android.internal.os.ZygoteInit 包的main函數:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
try {
…
registerZygoteSocket(); // Registers a server socket for zygote command
// load classs and resources
preloadClasses();
preloadResources();
…
// Do an initial gc to clean up after startup
gc();/*初始化GC垃圾回收機制*/
/* 通過從前面傳遞過來的第二個參數startsystemserver=”true” 啟動systemserver, 在startSystemServer()中會fork一個新的進程命名為system_server, 執行的是com.android.server包中的SystemServer.java文件中的main函數, 源碼位置:frameworks/base/services/java/com/android/server/ SystemServer.java。*/
if (argv[1].equals("true")) {
startSystemServer(); ///*************
} else if(…)
…
if (ZYGOTE_FORK_MODE) {
runForkMode(); /* ZYGOTE_FORK_MODE 永遠為flase */
} else {
runSelectLoopMode();/* Zygote進程進入無限循環,不再返回。接下來的zygote將會作為一個孵化服務進程來運行。*/
}
closeServerSocket();
}
…
} // end main()
從這里開始android啟動分為兩條線走,分別是:
startSystemServer(); ---------- Zygote的子進程
runSelectLoopMode(); /* Zygote進程進入無限循環,不再返回,執行孵化工作。*/
2.2.4 systemserver
上面的startSystemServer()函數中,做了如下的調用:
startSystemServer()
à Zygote.forkSystemServer()
à 父進程直接返回true,子進程執行handleSystemServerProcess()
à RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
/*
* Pass the remaining arguments to SystemServer.
* "--nice-name=system_server com.android.server.SystemServer"
*/
/*上面這個RuntimeInit包定於於文件frameworks\base\core\java\com\android\internal\os\RuntimeInit.java */
à invokeStaticMain(startClass, startArgs)
/* 通過該函數調用執行startClass類的main函數,帶參數 system_server 。*/
à ZygoteInit.MethodAndArgsCaller(m, argv)
/* 得到包com.android.server.SystemServer的main()函數。然后執行。*/
下面就開始調用到com.android.server.SystemServer類的main函數,源碼位於:
frameworks/base/services/java/com/android/server/SystemServer.java
This method is called from Zygote to initialize the system. This will cause the nativeservices (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call backup into init2() to start the Android services.
// main--->init1(system_init)--->init2(systemThread)
native public static void init1(String[] args);
public static void main(String[] args) {
...
System.loadLibrary("android_servers");// libandroid_servers.so是由目錄frameworks/base/services/jni下的源碼編譯所得
init1(args); // init1實際上是一個jni本地接口,位於文件frameworks\base\services\jni\com_android_server_SystemServer.cpp文件中system_init()函數
}
init1接口位於com_android_server_SystemServer.cpp中:
extern "C" int system_init();
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz){
system_init();
}
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"init1","([Ljava/lang/String;)V",(void*)
android_server_SystemServer_init1 },
};
而函數system_init()位於文件
frameworks\base\cmds\system_server\library\System_init.cpp
extern "C" status_t system_init()
{
…
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
if (!proc->supportsProcesses()) {
// Start the AudioFlinger
AudioFlinger::instantiate();
// Start the media playback service
MediaPlayerService::instantiate();
// Start the camera service
CameraService::instantiate();
// Start the audio policy service
AudioPolicyService::instantiate();
//start appc service
APPCService::instantiate();
}
…
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
runtime->callStatic("com/android/server/SystemServer", "init2");
// 執行com.android.server.SystemServer類的init2函數
…
}
com.android.server.SystemServer包的init2函數開啟一個ServerThread線程:
public static final void init2() {
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
ServerThread線程的run函數會啟動系統中絕大部分的android service,並最后進入Loop.loop(),,,,(SystemServer.java)
public void run() {
…
// Critical services...
try {
…
Slog.i(TAG, "Power Manager");
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
…
Slog.i(TAG, "Package Manager");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);
…
Slog.i(TAG, "Content Manager");
ContentService.main(context,
factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
…
Slog.i(TAG, "Battery Service");
battery = new BatteryService(context);
ServiceManager.addService("battery", battery);
…
其余addservice的過程類似,只是啟動的不同服務罷了,后面還啟動了很多
服務,如:Lights、Vibrator、Alarm、Sensor、Bluetooth、Input Method、NetStat、NetworkManagement、Connectivity、Mount、Notification、Audio等。 在這些服務都啟動完了之后。
…
…
… // run()函數的后半部分
// It is now time to start up the app processes...
使用xxx.systemReady()通知各個服務,系統已經就緒。
…
((ActivityManagerService)ActivityManagerNative.getDefault())
.systemReady(new Runnable() {
public void run() {
…
if (batteryF != null) batteryF.systemReady();
if (connectivityF != null) connectivityF.systemReady();
if (dockF != null) dockF.systemReady();
if (uiModeF != null) uiModeF.systemReady();
if (recognitionF != null) recognitionF.systemReady();
Watchdog.getInstance().start();
…
}
});
…
Looper.loop(); // Run the message queue in this thread。
…
}
2.2.5 home界面啟動
Home在
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady(.)
函數調用的過程中啟動,其中systemReady()的參數是一段callback代碼,如上面灰色顯示的部分。
這個函數的實現部分在文件:ActivityManagerService.java中。
public void systemReady(final Runnable goingCallback) {
…
if (mSystemReady) {
if (goingCallback != null) goingCallback.run();
return; // 執行回調
}
…
resumeTopActivityLocked(null);
}
private final boolean resumeTopActivityLocked(HistoryRecord prev) {
…
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
return startHomeActivityLocked();
}
…
}
private boolean startHomeActivityLocked() {
…
if (aInfo != null) {
…
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityLocked(null, intent, null, null, 0, aInfo,
null, null, 0, 0, 0, false, false); // 這里啟動home
}
}
…
}
三、android啟動圖示
參考網址:
1. http://blog.csdn.net/cuijianzhongswust/article/details/6612624
2. http://blog.csdn.net/sustzombie/article/details/6659622
3. http://www.docin.com/p-191202348.html
4. http://blog.csdn.net/maxleng/article/details/5508372
本文完。