Android開機流程跟蹤

android 系統的熟悉少不了對開機流程研究。因此這裏簡略看一下開機流程。 並沒有各個大佬的詳細,勿噴。

一、涉及的類文件:
./base/services/java/com/android/server/SystemServer.java
./base/core/java/com/android/internal/os/ZygoteInit.java
./base/core/java/com/android/internal/os/Zygote.java
./base/cmds/app_process/app_main.cpp
./base/core/java/com/android/internal/os/RuntimeInit.java
framework/base/core/jni/AndroidRuntime.cpp
......

二、android開機流程簡略圖
Android系統的開機流程主要部分有下面幾個,本篇文章主要是研究system server進程到啓動服務階段的源代碼。


三,Zygote進程的啓動

在.rc文件中腳本描述
在android 5.1.1的代碼中,*.rc  有64和32位的區別,因此比之前的版本多了幾個rc文件
./core/rootdir/init.trace.rc
./core/rootdir/init.zygote64_32.rc
./core/rootdir/init.rc
./core/rootdir/init.zygote64.rc
./core/rootdir/init.zygote32.rc
./core/rootdir/init.zygote32_64.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 media
onrestart restart netd
其中:  service , class ,socket 等的含義。
上面的--zygot --start-system-server --socket-name = zygote 爲參數配置。
上面的參數解析,在
./base/cmds/app_process/app_main.cpp  main()
方法中完成、。
int main(int argc, char* const argv[])
{
......
 
// Parse runtime arguments. Stop at first unrecognized option.
//這裏解析參數配置信息確定zygote 以及nicename等參數
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
 
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
......
//這裏設置process name 從配置信息我們可以看到,process name 爲zygote
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}
 
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
//參數配置錯誤
......
}
}
接下來在AndroidRuntime的start方法
framework/base/core/jni/AndroidRuntime.cpp
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
static const String8 startSystemServer("start-system-server");
......
創建根目錄/system ...
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
 
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
啓動虛擬機 
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
註冊JNI方法
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
 
...... 封裝className等參數信息 
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
重點在這裏,接下來進入ZygoteInit.java的main方法
//com.android.internal.os.ZygoteInit main
env->CallStaticVoidMethod(startClass, startMeth, strArray);
 
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
 
......
}
接下來在ZygoteInit.java中main方法
framework/base/core/java/com/android/internal/os/ZygoteInit.java
//fulairy
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)) { //SOCKET_NAME_ARG = --socket-name=
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
 
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
註冊socket監聽
registerZygoteSocket(socketName);
加載資源文件
preload(); 加載資源class,resource,library etc
觸發垃圾回收
// Do an initial gc to clean up after startup
gc();
 
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
 
runSelectLoop(abiList);
 
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
//MethodAndArgsCaller異常很重要
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
從後面的代碼跟蹤可以看到,startSystemServer會拋出MetthodAndArgsCaller異常,caller.run然後再去調用SystemServer的main方法。
三、system server 進程啓動
由startSystemServer方法,
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* 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,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
 
int pid;
 
try {
//這裏將參數封裝爲ZygoteConnection.Arguments 參數類型
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
 
/* Request to fork the system server process */
//爲啥不直接把parsedArgs傳遞過去就完了....因爲需要傳遞的信息只需要一部分,保證了程序安全性。
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
 
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
接下來 
handleSystemServerProcess(parsedArgs);
}
 
return true;
}
需要了解一下fork  method

handleSystemServerProcess
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
 
 
if (parsedArgs.invokeWith != null) {
......
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(cl);
}
 
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
 
/* should never reach here */
}
接下來在RuntimeInit的zygoteInit方法中
./base/core/java/com/android/internal/os/RuntimeInit.java
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.<p>
*
* Current recognized args:
* <ul>
* <li> <code> [--] &lt;start class name&gt; &lt;args&gt;
* </ul>
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 
redirectLogStreams(); // about print android log
//一下三個方法是比較重要的 
commonInit();//包含uncaughtexception,timezone,logmanager,HTTP user Agent,NetworkManagementSocketTagger
nativeZygoteInit(); // native init
//things init that pre  
applicationInit(targetSdkVersion, argv, classLoader);
}
這裏要特別看一下applicationInit 方法,算是上面幾個init方法中最重要的一個
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
 
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);//之前的版本好像沒有這個方法,應該是5.1中新增,設置sdk版本
 
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
 
// Remaining arguments are passed to the start class's static main
接下來有invokeStaticMain方法
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
* Invokes a static "main(argv[]) method on class "className".
* Converts various failing exceptions into RuntimeExceptions, with
* the assumption that they will then cause the VM instance to exit.
*
* @param className Fully-qualified class name
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
 
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
 
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
... the main method must be static main  
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
//之前我們在ZygoteInit.java中的main方法看到有MethoddAndArgsCaller異常的捕捉 caller.run() 
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
題外話: 從上面的流程跟蹤下來,個人感覺,google大佬們也在做一些優化,整合。比起4.x甚至3.x的版本。

接下來就是在SystemServer中的main方法,啓動各個system service

四、 SystemServer 啓動各個service
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
我們可以看到MethodAndArgsCaller 類中run實現,即 直接應用參數Method反射
   /**
884     * Helper exception class which holds a method and arguments and
885     * can call them. This is used as part of a trampoline to get rid of
886     * the initial process setup stack frames.
887     */
888    public static class MethodAndArgsCaller extends Exception
889            implements Runnable {
890        /** method to call */
891        private final Method mMethod;
892
893        /** argument array */
894        private final String[] mArgs;
895
896        public MethodAndArgsCaller(Method method, String[] args) {
897            mMethod = method;
898            mArgs = args;
899        }
900
901        public void run() {
902            try {
903                mMethod.invoke(null, new Object[] { mArgs });
904            } catch (IllegalAccessException ex) {
905                throw new RuntimeException(ex);
906            } catch (InvocationTargetException ex) {
907                Throwable cause = ex.getCause();
908                if (cause instanceof RuntimeException) {
909                    throw (RuntimeException) cause;
910                } else if (cause instanceof Error) {
911                    throw (Error) cause;
912                }
913                throw new RuntimeException(ex);
914            }
915        }
916    }

......  後面的世界面孔那就多了......
上面部分大致的流程圖就是這樣,圖畫的比較隨性,



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章