android開機啟動流程簡單分析
android啟動
當載入程式啟動Linux核心後,會載入各種驅動和資料結構,當有了驅動以後,開始啟動Android系統同時會載入使用者級別的第一個程序init(system\core\init\init.cpp)程式碼如下:
int main(int argc, char** argv) { ..... //建立資料夾,掛載 // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. if (is_first_stage) { mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); mount("sysfs", "/sys", "sysfs", 0, NULL); } ..... //列印日誌,設定log的級別 klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); ..... Parser& parser = Parser::GetInstance(); parser.AddSectionParser("service",std::make_unique<ServiceParser>()); parser.AddSectionParser("on", std::make_unique<ActionParser>()); parser.AddSectionParser("import", std::make_unique<ImportParser>()); // 載入init.rc配置檔案 parser.ParseConfig("/init.rc"); }
載入init.rc檔案,會啟動一個Zygote程序,此程序是Android系統的一個母程序,用來啟動Android的其他服務程序,程式碼:
從android L開始,在 /system/core/rootdir 目錄中有 4 個 zygote 相關的啟動指令碼如下圖:
在init.rc檔案中,有如下程式碼:
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
注意到上面的程式碼import /init.${ro.zygote}.rc,這裡會讀取ro.zygote這個屬性,匯入相應的init.rc檔案。
ro.zygote的屬性可為:zygote32、zygote64、zygote32_64、zygote64_32。
對於這個屬性的解釋如下。
init.zygote32.rc:zygote 程序對應的執行程式是 app_process (純 32bit 模式) init.zygote64.rc:zygote 程序對應的執行程式是 app_process64 (純 64bit 模式) init.zygote32_64.rc:啟動兩個 zygote 程序 (名為 zygote 和 zygote_secondary),對應的執行程式分別是 app_process32 (主模式)、app_process64。 init.zygote64_32.rc:啟動兩個 zygote 程序 (名為 zygote 和 zygote_secondary),對應的執行程式分別是 app_process64 (主模式)、app_process32
主流的機型屬性都為zygote64_32,我們來看看init.zygote64_32.rc檔案:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
在 linux 系統中,service 通常是一種被稱為守護程序 (daemon) 的程式。它通常在系統啟動時啟動,並一直運行於後臺,直到系統關閉時終止。
這裡會以service方式來啟動zygote程序,app_process的程式碼位於/frameworks/base/cmds/app_process/路徑下,該路徑下有一個檔案app_main.cpp,入口是main函式。
接下來看app_main.cpp函式,這裡實現從c++程式碼調到java程式碼:
int main(int argc, char* const argv[])
{
.....
//android執行時環境
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
.....
if (zygote) {
//啟動java程式碼
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
ZygoteInit.java 程式碼:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
.....
try {
.....
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
.....
//預載入android依賴的檔案
preload();
.....
if (startSystemServer) {
//啟動系統服務
startSystemServer(abiList, socketName);
}
.....
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
看這個類的main方法,最上面根據傳入的引數判斷是否將startSystemServer這個標記設為true,接著預載入android依賴的檔案,最後根據上面設定的標記來判斷是否能啟動系統服務。
接著看ZygoteInit.java中main方法在最後呼叫startSystemServer方法具體內容
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
.....
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
.....
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//Zygote程序開始fork子程序,啟動SystemServer
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
.....
}
SystemServer.java 程式碼
/frameworks/base/services/java/com/android/server/SystemServer.java
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
......
// Start services.
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
startBootstrapServices();
//啟動核心Service
startCoreServices();
//啟動其他Service
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
啟動SystemServer.java的startOtherServices方法
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
.....
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
.....
}
}
.....
}
ActivityManagerService.java中的mStackSupervisor.resumeFocusedStackTopActivityLocked()
public void systemReady(final Runnable goingCallback) {
.....
Slog.i(TAG, "System now ready");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
SystemClock.uptimeMillis());
.....
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
.....
//呼叫ActivityStackSupervisor中的resumeFocusedStackTopActivityLocked方法
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
}
}
ActivityStackSupervisor.java中的resumeFocusedStackTopActivityLocked方法
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
//呼叫ActivityStack中的resumeTopActivityUncheckedLocked來保證棧中的頂層Activity被重新啟動
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
return false;
}
ActivityStack.java中的resumeTopActivityUncheckedLocked方法
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
....
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
mService.updateSleepIfNeededLocked();
}
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
.....
if (next == null) {
// There are no more activities!
final String reason = "noMoreActivities";
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack()
? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
if (!mFullscreen && adjustFocusToNextFocusableStackLocked(returnTaskType, reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen.
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
mStackSupervisor.getFocusedStack(), prev, null);
}
// Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
//呼叫ActivityStackSupervisor中的方法來恢復 Launcher所在的棧
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
.....
}
ActivityStackSupervisor.java中resumeHomeStackTask方法
boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
.....
mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
ActivityRecord r = getHomeActivity();
final String myReason = reason + " resumeHomeStackTask";
// Only resume home activity if isn't finishing.
if (r != null && !r.finishing) {
mService.setFocusedActivityLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
啟動launcher應用的鎖屏介面
return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
Android系統啟動完成,打開了Launcher應用的Home介面。
歡迎關注我的公眾號 ,不定期會有優質技術文章推送 。
微信掃一掃下方二維碼即可關注