android:process=.server,Android启动(三)----开启SystemServer进程
前面已經(jīng)講到,從C/C++層進(jìn)入了Java層,即調(diào)用了ZygoteInit.main()函數(shù),那么接下來(lái)會(huì)發(fā)生什么事情呢?
源碼參考Android4.1.1,涉及的文件有ZygoteInit.java,RuntimeInit.java(framework文件夾下)
ZygoteInit.main():
public static void main(String argv[]) {
try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
//創(chuàng)建服務(wù)端的socket
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 最終調(diào)用preloadClasses();preloadResources();兩個(gè)函數(shù),
//加載class文件和res資源
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
gc();
//這里的argv就是在C層產(chǎn)生的字符串?dāng)?shù)組,有兩個(gè)元素
// If requested, start system server directly from Zygote
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
//顯然,條件成立
if (argv[1].equals("start-system-server")) {
//這是要真刀真槍的開(kāi)啟SS進(jìn)程了
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
//這個(gè)函數(shù)其實(shí)也很重要,簡(jiǎn)而言之,讓zygote休眠,但是隨時(shí)能接受消息
//從loop字眼也可以看出循環(huán)的意思,后面的文章會(huì)在提到這個(gè)
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
再看看startSystemServer()函數(shù)
private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */
String args[] = {//參數(shù)
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(//fork一個(gè)子進(jìn)程
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) {//子進(jìn)程,即system_server進(jìn)程
handleSystemServerProcess(parsedArgs);
}
return true;
}
果然看到了forkSystemServer這樣的函數(shù)了,接下來(lái)在子進(jìn)程中調(diào)用了handleSystemServerProcess()函數(shù):
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();
// set umask to 0077 so new files and directories will default to owner-only permissions.
FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);
//niceName?
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
/*
* Pass the remaining arguments to SystemServer.
*/
//顯然就是這個(gè)函數(shù)最重要了,
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}
需要注意的是zygoteInit()函數(shù)是RuntimeInit類(lèi)直接調(diào)用的,說(shuō)明它是靜態(tài)函數(shù),在RuntimeInit.java文件中,zygoteInit()函數(shù)如下:
/**
* 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.
*
* Current recognized args:
*
*
[--]*
*
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
//本地zygoteInit函數(shù),主要職責(zé)是C++層的初始化
nativeZygoteInit();
//另外的一些初始化工作
applicationInit(targetSdkVersion, argv);
}
本地的zygoteInit函數(shù)我們先放在一邊,先看applicationInit函數(shù):
private static void applicationInit(int targetSdkVersion, String[] argv)
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);
final Arguments args;
try {
//一些參數(shù)設(shè)定
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
//英文解釋的其實(shí)已經(jīng)比較明白了,
invokeStaticMain(args.startClass, args.startArgs);
}
再來(lái)看看invokeStaticMain函數(shù),很明顯,調(diào)用了JNI.
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
//獲取類(lèi)對(duì)象
cl = Class.forName(className);
} 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);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* 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);
##居然主動(dòng)拋出異常?!!,what‘s the shit?
}
好吧,我在手心連寫(xiě)十個(gè)“忍”,繼續(xù)還是心平氣和的看代碼,其實(shí)只要往上追溯,由于上層的方法都選擇拋出該異常,最終追溯到了ZygoteInit.main()方法中,
在回顧main函數(shù)(部分):
try {
.........
.........
.........
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
runSelectLoopMode();
}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
##shit!!,在這里catch到了這個(gè)異常,看來(lái)是有意為之了
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
好,caller對(duì)象是(MethodAndArgsCaller類(lèi)型的,繼續(xù)看caller.run()做了什么:
......
......
public void run() {
try {
##kidding me ??!!,在這里調(diào)用了SystemServer.main()方法?
mMethod.invoke(null, new Object[] { mArgs });
//有興趣的同學(xué)可以研究一下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);
}
}
問(wèn)題到這里可以說(shuō)結(jié)束了,最終(fork的子進(jìn)程)調(diào)用了SystemServer.main()函數(shù),相當(dāng)于創(chuàng)造了SystemS進(jìn)程。
那么問(wèn)題來(lái)了,為什么不在主動(dòng)拋出異常的的地方直接調(diào)用main方法?
說(shuō)實(shí)話(huà),我不是很理解,但是看了鄧平凡大大的《深入理解Android I》(是本好書(shū),值得推薦),里面給出了一種解釋那就是釋放堆棧中被浪費(fèi)的資源。
稍微解釋一下,就是函數(shù)的調(diào)用是需要利用調(diào)用堆棧來(lái)實(shí)現(xiàn)的,每調(diào)用一個(gè)函數(shù),原來(lái)的函數(shù)的資源會(huì)被壓入棧,如果嵌套調(diào)用的函數(shù)多了的話(huà),會(huì)占用系統(tǒng)資源。而關(guān)鍵在于SystemServer進(jìn)程是不會(huì)死的(如果死了的話(huà),系統(tǒng)也掛掉了),所以,也就意味著在這之前占用的那些資源不會(huì)被釋放,so.......
多說(shuō)一句,這種方式似乎達(dá)成了exec的函數(shù)調(diào)用的效果,上一篇文章提到,fork往往和exec一起用,可以造就兩個(gè)不同的進(jìn)程,但是實(shí)際上exec系統(tǒng)調(diào)用的工作原理是替換原來(lái)的進(jìn)程的執(zhí)行內(nèi)容,只保留進(jìn)程ID,可以說(shuō)exec系統(tǒng)調(diào)用會(huì)擦除之前的進(jìn)程積壓的資源,這種拋異常的方式從某種程度上來(lái)講實(shí)現(xiàn)了exec的效果。
總結(jié)
以上是生活随笔為你收集整理的android:process=.server,Android启动(三)----开启SystemServer进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 哈理工计算机分数线2020,2021哈尔
- 下一篇: 在计算机中常用的数据表示方法有哪些,数据