1. Boot系統初始化, 具體過程參見(system/core/init/Init.c)中的main函數,這時候,手機或者模擬器出現的畫面是一個console,顯示“ANDROID”msg。
if (fd >= 0) {<br /> const char *msg;<br /> msg = "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n" // console is 40 cols x 30 lines<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> "/n"<br /> " A N D R O I D ";<br /> write(fd, msg, strlen(msg));<br /> close(fd);<br /> }<br /> }
2.mount 的過程--> 初始化成功後,就開始mounting系統,具體參見(system/core/mountd/Mountd.c) 中的main函數。
mkdir("/dev", 0755);<br /> mkdir("/proc", 0755);<br /> mkdir("/sys", 0755);<br /> mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");<br /> mkdir("/dev/pts", 0755);<br /> mkdir("/dev/socket", 0755);<br /> mount("devpts", "/dev/pts", "devpts", 0, NULL);<br /> mount("proc", "/proc", "proc", 0, NULL);<br /> mount("sysfs", "/sys", "sysfs", 0, NULL);
3.接下來運行androidRuntime,並開始啟動java虛擬機器dalvikvm。
4. Java虛擬機器啟動成功後,開始系統初始化。系統初始的第一步是用JNI方式實現的,對應java代碼為(frameworks/base/services/java/com/android/server/SystemServer.java) init1(Native)函數,對應的JNI C++代碼為(frameworks/base/core/jni/server/com_android_server_SystemServer.cpp),而實現的C++代碼為
(frameworks/base/cmds/system_server/library/ System_init.cpp) 中的system_init()函數。
5. system_init調用SurfaceFlinger,SurfaceFlinger的readyToRun()函數用BootAnimation來實現開機動畫,這時候手機或者模擬器顯示是一副背景圖加一個動態小機器人。
6. 系統初始化的第二步,將啟動ServerThread進程,參見SystemServer.init2()。ServerThread將啟動各種系統服務,如Power Manager、Activity Manager等等,具體參見ServerThread的run函數,ServerThread同在SystemServer.java中。
7.這之後的事,應該就是進入系統了。(這部分沒有調查過)。
--------------------------------------------------------------------------------
對於關注Android底層的朋友來說,其具體的啟動過程應該是比較吸引我們的。但是很多開機檔案什麼的,都得adb push到host上來看,挺不方便的,都怪Android內建的Toolbox太簡略了。所以在深入瞭解Android的啟動流程之前,我們來把Busybox安裝到Android上去,這樣,就有很多工具供我們使用了。
首先去busybox首頁 下載最新版本的原始碼,然後用arm的交叉編譯器編譯出busybox的可執行程式,編譯的時候需要注意一些設定選項,例如
Build Options —>
Build BusyBox as a static binary (no shared libs) 這個要選上,因上這樣子編譯出來的busyBox才是可以獨立啟動並執行。
│Do you want to build BusyBox with a Cross Compiler? │ │
│ │(/HOME/toolchains/gcc-4.0.2-glibc-2.3.5/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu│ 這是交叉編譯器的路徑,要根據具體的情況來設定。
Installation Options —>
Don’t use /usr
這樣子編譯出來的busybox才不會安裝到你主機的/usr目錄下。一定要選上。
busybox的功能選項根據需要自選,但是不要太貪心.
OK,這裡就不糾纏於編譯busybox的東西了,網上資料無數。接下來,我們把busybox安裝到模擬器上去。先在模擬器上隨便建一個busybox的檔案夾,然後進入busybox可執行檔目錄,使用命令
adb push busybox.asc /data/busybox/busybox
然後進入adb shell,chmod 777 ./busybox,就可以直接使用了。但現在還是不方便,總不能每用一個命令就輸一次busybox吧?所以,我們可以先用./busybox --install將程式都安裝到目前的目錄下,然後把目前的目錄添加到PATH變數中即可。暫時使用export來添加吧,如果想永久添加,往下看。
好了,準備工作完成,開始研究的工作了。既然是研究啟動過程,那當然是先看看init.rc檔案。去etc目錄開啟它,分析一下內容,首先是對 env的定義,也就是全域環境變數的定義,接下來的建立和初始化裡面的內容目前還不清楚什麼意思,緊接著就是系統啟動時啟動並執行初始進程資訊,這個比較有意思,包括了usbd-config和qemu,qemu自不用說,而usbd-config作為初始啟動的進程,應該就是和上一篇文章猜的一樣,用來調試或者usb通訊的。往下看,是在初始啟動進程完成之後開始啟動的服務進程,這些進程如果因故退出,會自動重啟。這裡麵包括了console控制台,adbd監護進程,usbd監護進程,debuggerd監護進程等.除去這些守護進程,能引起我們注意的,是runtime和zygote。這兩個進程似乎掌管著其他進程以及應用程式的啟動。
現在,來讓我們做一個實驗吧,將自動調用的啟動過程變成手動,看看啟動流程具體是什麼樣的。想達到這個目的,首先就是要修改init.rc檔案,當然不是在模擬器的console中改,一是不能改,二是你改了也沒用,下次載入就會給你覆蓋了。所以,我們要從原始鏡像ramdisk.img入手了。從2.6標準Linux核心開始,initrd.img都採用cpio壓縮,猜測ramdisk.img也一樣,需要使用gunzip解壓縮,然後再使用cpio解包。好,進入tools/lib/images目錄下,先用file命令看看ramdisk.img的類型,沒錯,系統提示
ramdisk.img: gzip compressed data, from Unix
很好,然後將ramdisk.img複製一份到任何其他目錄下,將其名稱改為ramdisk.img.gz,並使用命令
gunzip ramdisk.img.gz
然後建立一個檔案夾,叫ramdisk吧,進入,輸入命令
cpio -i -F ../ramdisk.img
這下,你就能看見並操作ramdisk裡面的內容了。當然你也可以直接在外面進行操作,但是還是建議把cpio解壓縮出來的內容全部集中在一個檔案夾裡面,因為一會我們還要將其壓縮成新的ramdisk.img。
OK,現在開始修改步驟吧。用任何一款編輯器開啟init.rc,首先在PATH那裡加上你的Busybox安裝路徑,然後注釋內容,我們要手工啟動他們。
# zygote { # exec /system/bin/app_process # args { # 0 -Xzygote # 1 /system/bin # 2 –zygote # } # autostart 1 # }# runtime { # exec /system/bin/runtime # autostart 1 # }
在這裡需要注意,不要同時把兩者都注釋了,注釋某一個,再實驗手工啟動它,如果兩者同時注釋我這裡有問題,無法啟動。
好,接下來,使用下列命令重新打包成鏡像
cpio -i -t -F ../ramdisk.img > list
cpio -o -H newc -O lk.img < list
目前的目錄下產生的lk.img就是我們的新鏡像了。使用自己的鏡像啟動emulator;
emulator -console -ramdisk lk.img
如果我們注釋的是zygote,那麼在#後輸入
app_process -Xzygote /system/bin –zygote
手工啟動,命令列中輸出的資訊是
Prepping: /system/app/AlarmProvider.apk:/system/app/Browser.apk:/system/app/
Calendar.apk:/system/app/Camera.apk:/system/app/Contacts.apk:
/system/app/Development.apk:/system/app/GDataFeedsProvider.apk:/system/app/
Gmail.apk:/system/app/GmailProvider.apk:/system/app/GoogleApps.apk:
/system/app/GoogleAppsProvider.apk:/system/app/Home.apk:/system/app/ImProvider.apk:
/system/app/Maps.apk:/system/app/MediaPickerActivity.apk:
/system/app/MediaProvider.apk:/system/app/Phone.apk:/system/app/PimProvider.apk:/system/
app/ApiDemos.apk:/system/app/SettingsProvider.apk:
/system/app/Sms.apk:/system/app/SyncProvider.apk:/system/app/TelephonyProvider.apk:
/system/app/XmppService.apk:/system/app/YouTube.apk
File not found: /system/app/AlarmProvider.apk
File not found: /system/app/Calendar.apk
File not found: /system/app/Camera.apk
File not found: /system/app/GDataFeedsProvider.apk
File not found: /system/app/Gmail.apk
File not found: /system/app/GmailProvider.apk
File not found: /system/app/MediaPickerActivity.apk
File not found: /system/app/PimProvider.apk
File not found: /system/app/ApiDemos.apk
File not found: /system/app/Sms.apk
File not found: /system/app/SyncProvider.apk
File not found: /system/app/YouTube.apk
Prep complete
嘿嘿,從File not found的資訊中可以看到一些Google可能會即將推出的應用,比如Gmail什麼的。當然,這些都是Java架構的啟動資訊,我們以後還要藉助其他工具來進行進一步探索。
如果我們注釋的是runtime,那麼輸出資訊是: