本文轉載自Gityuan的博客,原文地址為:http://gityuan.com/2016/02/14/android-system-server/
轉載請注明作者及原文鏈接。
基于Android 6.0的源碼剖析, 分析Android啟動過程的system_server進程
/frameworks/base/core/java/com/android/internal/os/
- ZygoteInit.java
- RuntimeInit.java
- Zygote.java
/frameworks/base/core/services/java/com/android/server/
- SystemServer.java
/frameworks/base/core/jni/
- com_android_internal_os_Zygote.cpp
- AndroidRuntime.cpp
/frameworks/base/cmds/app_process/App_main.cpp
啟動流程
SystemServer的在Android體系中所處的地位,SystemServer由Zygote fork生成的,進程名為system_server
,該進程承載著framework的核心服務。 Android系統啟動-zygote篇中講到Zygote啟動過程中會調用startSystemServer(),可知startSystemServer()
函數是system_server啟動流程的起點, 啟動流程圖如下:
上圖前4步驟(即顏色為紫色的流程)運行在是Zygote
進程,從第5步(即顏色為藍色的流程)ZygoteInit.handleSystemServerProcess開始是運行在新創建的system_server
,這是fork機制實現的(fork會返回2次)。下面從startSystemServer()開始講解詳細啟動流程。
1. startSystemServer
[–>ZygoteInit.java]
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {
...
//參數準備
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",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//用于解析參數,生成目標格式
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
// fork子進程,該進程是system_server進程【見小節2】
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//進入子進程system_server
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 完成system_server進程剩余的工作 【見小節5】
handleSystemServerProcess(parsedArgs);
}
return true;
}
準備參數并fork新進程,從上面可以看出system server進程參數信息為uid=1000,gid=1000,進程名為sytem_server,從zygote進程fork新進程后,需要關閉zygote原有的socket。另外,對于有兩個zygote進程情況,需等待第2個zygote創建完成。
2 forkSystemServer
[–>Zygote.java]
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
// 調用native方法fork system_server進程【見小節3】
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
if (pid == 0) {
Trace.setTracingEnabled(true);
}
VM_HOOKS.postForkCommon();
return pid;
}
nativeForkSystemServer()方法在AndroidRuntime.cpp中注冊的,調用com_android_internal_os_Zygote.cpp中的register_com_android_internal_os_Zygote()方法建立native方法的映射關系,所以接下來進入如下方法。
3. nativeForkSystemServer
[–>com_android_internal_os_Zygote.cpp]
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
jlong effectiveCapabilities) {
//fork子進程,見【見小節4】
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0) {
// zygote進程,檢測system_server進程是否創建
gSystemServerPid = pid;
int status;
if (waitpid(pid, &status, WNOHANG) == pid) {
//當system_server進程死亡后,重啟zygote進程
RuntimeAbort(env);
}
}
return pid;
}
當system_server進程創建失敗時,將會重啟zygote進程。這里需要注意,對于Android 5.0以上系統,有兩個zygote進程,分別是zygote、zygote64兩個進程,system_server的父進程,一般來說64位系統其父進程是zygote64進程
- 當kill system_server進程后,只重啟zygote64和system_server,不重啟zygote;
- 當kill zygote64進程后,只重啟zygote64和system_server,也不重啟zygote;
- 當kill zygote進程,則重啟zygote、zygote64以及system_server。
4. ForkAndSpecializeCommon
[–>com_android_internal_os_Zygote.cpp]
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jstring instructionSet, jstring dataDir) {
SetSigChldHandler(); //設置子進程的signal信號處理函數
pid_t pid = fork(); //fork子進程
if (pid == 0) {
//進入子進程
DetachDescriptors(env, fdsToClose); //關閉并清除文件描述符
if (!is_system_server) {
//對于非system_server子進程,則創建進程組
int rc = createProcessGroup(uid, getpid());
}
SetGids(env, javaGids); //設置設置group
SetRLimits(env, javaRlimits); //設置資源limit
int rc = setresgid(gid, gid, gid);
rc = setresuid(uid, uid, uid);
SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env); //設置調度策略
//selinux上下文
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
if (se_info_c_str == NULL && is_system_server) {
se_name_c_str = "system_server";
}
if (se_info_c_str != NULL) {
SetThreadName(se_name_c_str); //設置線程名為system_server,方便調試
}
UnsetSigChldHandler(); //設置子進程的signal信號處理函數為默認函數
//等價于調用zygote.callPostForkChildHooks()
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server ? NULL : instructionSet);
...
} else if (pid > 0) {
//進入父進程,即zygote進程
}
return pid;
}
fork()創建新進程,采用copy on write方式,這是linux創建進程的標準方法,會有兩次return,對于pid==0為子進程的返回,對于pid>0為父進程的返回。 到此system_server進程已完成了創建的所有工作,接下來開始了system_server進程的真正工作。在前面startSystemServer()方法中,zygote進程執行完forkSystemServer()后,新創建出來的system_server進程便進入handleSystemServerProcess()方法。關于fork(),可查看另一個文章理解Android進程創建流程。
5. handleSystemServerProcess
[–>ZygoteInit.java]
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket(); //關閉父進程zygote復制而來的Socket
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName); //設置當前進程名為"system_server"
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
//執行dex優化操作【見小節6】
performSystemServerDexOpt(systemServerClasspath);
}
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
//啟動應用進程
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 創建類加載器,并賦予當前線程
cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(cl);
}
//system_server故進入此分支【見小節7】
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
此處systemServerClasspath
環境變量主要有/system/framework/目錄下的services.jar,ethernet-service.jar, wifi-service.jar這3個文件
6. performSystemServerDexOpt
[–>ZygoteInit.java]
private static void performSystemServerDexOpt(String classPath) {
final String[] classPathElements = classPath.split(":");
//創建一個與installd的建立socket連接
final InstallerConnection installer = new InstallerConnection();
//執行ping操作,直到與installd服務端連通為止
installer.waitForConnection();
final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
try {
for (String classPathElement : classPathElements) {
final int dexoptNeeded = DexFile.getDexOptNeeded(
classPathElement, "*", instructionSet, false /* defer */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
//以system權限,執行dex文件優化
installer.dexopt(classPathElement, Process.SYSTEM_UID, false,
instructionSet, dexoptNeeded);
}
}
} catch (IOException ioe) {
throw new RuntimeException("Error starting system_server", ioe);
} finally {
installer.disconnect(); //斷開與installd的socket連接
}
}
將classPath字符串中的apk,分別進行dex優化操作。真正執行優化工作通過socket通信將相應的命令參數,發送給installd來完成。
7. zygoteInit
[–>RuntimeInit.java]
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams(); //重定向log輸出
commonInit(); // 通用的一些初始化【見小節8】
nativeZygoteInit(); // zygote初始化 【見小節9】
applicationInit(targetSdkVersion, argv, classLoader); // 應用初始化【見小節10】
}
8. commonInit
[–>RuntimeInit.java]
private static final void commonInit() {
// 設置默認的未捕捉異常處理方法
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
// 設置市區,中國時區為"Asia/Shanghai"
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
//重置log配置
LogManager.getLogManager().reset();
new AndroidConfig();
// 設置默認的HTTP User-agent格式,用于 HttpURLConnection。
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
// 設置socket的tag,用于網絡流量統計
NetworkManagementSocketTagger.install();
}
默認的HTTP User-agent格式,例如:
"Dalvik/1.1.0 (Linux; U; Android 6.0.1;LenovoX3c70 Build/LMY47V)".
9. nativeZygoteInit
nativeZygoteInit()方法在AndroidRuntime.cpp中,進行了jni映射,對應下面的方法。
[–>AndroidRuntime.cpp]
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) {
//此處的gCurRuntime為AppRuntime,是在AndroidRuntime.cpp中定義的
gCurRuntime->onZygoteInit();
}
[–>app_main.cpp]
virtual void onZygoteInit() {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool(); //啟動新binder線程
}
ProcessState::self()是單例模式,主要工作是調用open()打開/dev/binder驅動設備,再利用mmap()映射內核的地址空間,將Binder驅動的fd賦值ProcessState對象中的變量mDriverFD,用于交互操作。startThreadPool()是創建一個新的binder線程,不斷進行talkWithDriver(),在binder系列文章中的注冊服務(addService)詳細這兩個方法的執行原理。
10. applicationInit
[–>RuntimeInit.java]
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
//true代表應用程序退出時不調用AppRuntime.onExit(),否則會在退出前調用
nativeSetExitWithoutCleanup(true);
//設置虛擬機的內存利用率參數值為0.75
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv); //解析參數
} catch (IllegalArgumentException ex) {
return;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//調用startClass的static方法 main() 【見小節11】
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
在startSystemServer()方法中通過硬編碼初始化參數,可知此處args.startClass為”com.android.server.SystemServer”。
11. invokeStaticMain
[–>RuntimeInit.java]
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl = Class.forName(className, true, classLoader);
...
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
...
} catch (SecurityException ex) {
...
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
...
}
//通過拋出異常,回到ZygoteInit.main()。這樣做好處是能清空棧幀,提高棧幀利用率。【見小節12】
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
12. MethodAndArgsCaller
在Android系統啟動-zygote篇中遺留了一個問題沒有講解,如下:
[–>ZygoteInit.java]
public static void main(String argv[]) {
try {
startSystemServer(abiList, socketName);//啟動system_server
....
} catch (MethodAndArgsCaller caller) {
caller.run(); //【見小節13】
} catch (RuntimeException ex) {
closeServerSocket();
throw ex;
}
}
現在已經很明顯了,是invokeStaticMain()方法中拋出的異常MethodAndArgsCaller
,從而進入caller.run()方法。
[–>ZygoteInit.java]
public static class MethodAndArgsCaller extends Exception implements Runnable {
public void run() {
try {
//根據傳遞過來的參數,可知此處通過反射機制調用的是SystemServer.main()方法
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
到此,總算是進入到了SystemServer類的main()方法, 在文章Android系統啟動-SystemServer下篇中會緊接著這里開始講述。