Android5 Zygote 涓?SystemServer 鍚姩娴佺▼鍒嗘瀽
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android5 Zygote 涓?SystemServer 鍚姩娴佺▼鍒嗘瀽相关的知识,希望对你有一定的参考价值。
鏍囩锛?/p>
android5 Zygote 涓?SystemServer 鍚姩娴佺▼鍒嗘瀽
鍓嶈█
Android5.0.1 鐨勫惎鍔ㄦ祦绋嬩笌涔嬪墠鐨勭増鏈浉姣斿彉鍖栧苟涓嶅ぇ锛孫K锛屽彉鍖栬櫧鐒惰繕鏄湁锛歋ystemServer 鍚姩杩囩▼鐨?init1(), init2()娌℃湁浜嗭紝浣嗕富骞叉祦绋嬩緷鐒朵笉鍙橈細Linux 鍐呮牳鍔犺浇瀹屾瘯涔嬪悗锛岄鍏堝惎鍔?init 杩涚▼锛岀劧鍚庤В鏋?init.rc锛屽苟鏍规嵁鍏跺唴瀹圭敱 init 杩涚▼瑁呰浇 Android 鏂囦欢绯荤粺銆佸垱寤虹郴缁熺洰褰曘€佸垵濮嬪寲灞炴€х郴缁熴€佸惎鍔ㄤ竴浜涘畧鎶よ繘绋嬶紝鍏朵腑鏈€閲嶈鐨勫畧鎶よ繘绋嬪氨鏄?Zygote 杩涚▼銆俍ygote 杩涚▼鍒濆鍖栨椂浼氬垱寤?Dalvik 铏氭嫙鏈恒€侀瑁呰浇绯荤粺鐨勮祫婧愬拰 Java 绫汇€傛墍鏈変粠 Zygote 杩涚▼ fork 鍑烘潵鐨勭敤鎴疯繘绋嬮兘灏嗙户鎵垮拰鍏变韩杩欎簺棰勫姞杞界殑璧勬簮銆俰nit 杩涚▼鏄?Android 鐨勭涓€涓繘绋嬶紝鑰?Zygote 杩涚▼鍒欐槸鎵€鏈夌敤鎴疯繘绋嬬殑鏍硅繘绋嬨€係ystemServer 鏄?Zygote 杩涚▼ fork 鍑虹殑绗竴涓繘绋嬶紝涔熸槸鏁翠釜 Android 绯荤粺鐨勬牳蹇冭繘绋嬨€?/p>
zygote 杩涚▼
瑙f瀽 zygote.rc
鍦ㄦ枃浠朵腑 /system/core/rootdir/init.rc 涓寘鍚簡 zygote.rc:
import /init.${ro.zygote}.rc
${ro.zygote}鏄钩鍙扮浉鍏崇殑鍙傛暟锛屽疄闄呭彲瀵瑰簲鍒?init.zygote32.rc锛?init.zygote64.rc锛?init.zygote64_32.rc锛?init.zygote32_64.rc锛屽墠涓や釜鍙細鍚姩鍗曚竴app_process(64) 杩涚▼锛岃€屽悗涓や釜鍒欎細鍚姩涓や釜app_process杩涚▼锛氱浜屼釜app_process杩涚▼绉颁负 secondary锛屽湪鍚庨潰鐨勪唬鐮佷腑鍙互鐪嬪埌鐩稿簲 secondary socket 鐨勫垱寤鸿繃绋嬨€備负绠€鍖栬捣瑙侊紝鍦ㄨ繖閲屽氨涓嶈€冭檻杩欑鍒涘缓涓や釜app_process杩涚▼鐨勬儏褰€?/p>
浠?/system/core/rootdir/init.zygote32.rc 涓轰緥锛?/p>
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
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
绗竴琛屽垱寤轰簡鍚嶄负 zygote 鐨勮繘绋嬶紝杩欎釜杩涚▼鏄€氳繃 app_process 鐨?main 鍚姩骞朵互鈥?Xzygote /system/bin 鈥搝ygote 鈥搒tart-system-server鈥濅綔涓簃ain鐨勫叆鍙e弬鏁般€?/p>
app_process 瀵瑰簲浠g爜涓?framework/base/cmds/app_process/app_main.cpp銆傚湪杩欎釜鏂囦欢鐨刴ain鍑芥暟涓細
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
}
鏍规嵁鍏ュ彛鍙傛暟锛屾垜浠煡閬?zygote 涓簍rue锛宎rgs鍙傛暟涓寘鍚簡鈥漵tart-system-server鈥濄€?/p>
AppRuntime 缁ф壙鑷?AndroidRuntime锛屽洜姝や笅涓€姝ュ氨鎵ц鍒?AndroidRuntime 鐨?start 鍑芥暟銆?/p>
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
/* start the virtual machine */ // 鍒涘缓铏氭嫙鏈?/span>
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
...
//璋冪敤className瀵瑰簲绫荤殑闈欐€乵ain()鍑芥暟
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
env->CallStaticVoidMethod(startClass, startMeth, strArray);
...
}
start鍑芥暟涓昏鍋氫袱浠朵簨锛氬垱寤鸿櫄鎷熸満鍜岃皟鐢ㄤ紶鍏ョ被鍚嶅搴旂被鐨?main 鍑芥暟銆傚洜姝や笅涓€姝ュ氨鎵ц鍒?com.android.internal.os.ZygoteInit 鐨?main 鍑芥暟銆?/p>
public static void main(String argv[]) {
try {
boolean startSystemServer = false;
String socketName = "zygote";
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
}
...
}
registerZygoteSocket(socketName);
...
preload();
...
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
瀹冧富瑕佸仛浜嗕笁浠朵簨鎯?
1. 璋冪敤 registerZygoteSocket 鍑芥暟鍒涘缓浜嗕竴涓?socket 鎺ュ彛锛岀敤鏉ュ拰 ActivityManagerService 閫氳锛?
2. 璋冪敤 startSystemServer 鍑芥暟鏉ュ惎鍔?SystemServer;
3. 璋冪敤 runSelectLoop 鍑芥暟杩涘叆涓€涓棤闄愬惊鐜湪鍓嶉潰鍒涘缓鐨?socket 鎺ュ彛涓婄瓑寰?ActivityManagerService 璇锋眰鍒涘缓鏂扮殑搴旂敤绋嬪簭杩涚▼銆?/p>
杩欓噷瑕佺暀鎰?catch (MethodAndArgsCaller caller) 杩欎竴琛岋紝android 鍦ㄨ繖閲岄€氳繃鎶涘嚭涓€涓紓甯告潵澶勭悊姝e父鐨勪笟鍔¢€昏緫銆?/p>
socket zygote stream 660 root system
绯荤粺鍚姩鑴氭湰鏂囦欢 init.rc 鏄敱 init 杩涚▼鏉ヨВ閲婃墽琛岀殑锛岃€?init 杩涚▼鐨勬簮浠g爜浣嶄簬 system/core/init 鐩綍涓紝鍦?init.c 鏂囦欢涓紝鏄敱 service_start 鍑芥暟鏉ヨВ閲?init.zygote32.rc 鏂囦欢涓殑 service 鍛戒护鐨勶細
void service_start(struct service *svc, const char *dynamic_args)
{
...
pid = fork();
if (pid == 0) {
struct socketinfo *si;
...
for (si = svc->sockets; si; si = si->next) {
int socket_type = (
!strcmp(si->type, "stream") ? SOCK_STREAM :
(!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
int s = create_socket(si->name, socket_type,
si->perm, si->uid, si->gid, si->socketcon ?: scon);
if (s >= 0) {
publish_socket(si->name, s);
}
}
...
}
...
}
姣忎竴涓?service 鍛戒护閮戒細淇冧娇 init 杩涚▼璋冪敤 fork 鍑芥暟鏉ュ垱寤轰竴涓柊鐨勮繘绋嬶紝鍦ㄦ柊鐨勮繘绋嬮噷闈紝浼氬垎鏋愰噷闈㈢殑 socket 閫夐」锛屽浜庢瘡涓€涓?socket 閫夐」锛岄兘浼氶€氳繃 create_socket 鍑芥暟鏉ュ湪 /dev/socket 鐩綍涓嬪垱寤轰竴涓枃浠讹紝鍦?zygote 杩涚▼涓?socket 閫夐」涓衡€渟ocket zygote stream 660 root system鈥濓紝鍥犳杩欎釜鏂囦欢渚挎槸 zygote浜嗭紝鐒跺悗寰楀埌鐨勬枃浠舵弿杩扮閫氳繃 publish_socket 鍑芥暟鍐欏叆鍒扮幆澧冨彉閲忎腑鍘伙細
static void publish_socket(const char *name, int fd)
{
char key[64] = ANDROID_SOCKET_ENV_PREFIX;
char val[64];
strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
name,
sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
snprintf(val, sizeof(val), "%d", fd);
add_environment(key, val);
/* make sure we don鈥榯 close-on-exec */
fcntl(fd, F_SETFD, 0);
}
杩欓噷浼犺繘鏉ョ殑鍙傛暟name鍊间负鈥漽ygote鈥濓紝鑰?ANDROID_SOCKET_ENV_PREFIX 鍦?system/core/include/cutils/sockets.h 瀹氫箟涓猴細
#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
#define ANDROID_SOCKET_DIR "/dev/socket"
鍥犳锛岃繖閲屽氨鎶婁笂闈㈠緱鍒扮殑鏂囦欢鎻忚堪绗﹀啓鍏ュ埌浠?鈥淎NDROID_SOCKET_zygote鈥?涓?key 鍊肩殑鐜鍙橀噺涓€傚張鍥犱负涓婇潰鐨?ZygoteInit.registerZygoteSocket 鍑芥暟涓庤繖閲屽垱寤?socket 鏂囦欢鐨?create_socket 鍑芥暟鏄繍琛屽湪鍚屼竴涓繘绋嬩腑锛屽洜姝わ紝涓婇潰鐨?ZygoteInit.registerZygoteSocket 鍑芥暟鍙互鐩存帴浣跨敤杩欎釜鏂囦欢鎻忚堪绗︽潵鍒涘缓涓€涓?Java灞傜殑LocalServerSocket 瀵硅薄銆傚鏋滃叾瀹冭繘绋嬩篃闇€瑕佹墦寮€杩欎釜 /dev/socket/zygote 鏂囦欢鏉ュ拰 zygote 杩涚▼杩涜閫氫俊锛岄偅灏卞繀椤昏閫氳繃鏂囦欢鍚嶆潵杩炴帴杩欎釜 LocalServerSocket浜嗐€備篃灏辨槸璇村垱寤?zygote socket 涔嬪悗锛孉ctivityManagerService 灏辫兘澶熼€氳繃璇?socket 涓?zygote 杩涚▼閫氫俊浠庤€?fork 鍒涘缓鏂拌繘绋嬶紝android 涓殑鎵€鏈夊簲鐢ㄨ繘绋嬮兘鏄€氳繃杩欑鏂瑰紡 fork zygote 杩涚▼鍒涘缓鐨勩€傚湪 ActivityManagerService涓?鐨?startProcessLocked 涓皟鐢ㄤ簡Process.start()鏂规硶锛岃繘鑰岃皟鐢?Process.startViaZygote 鍜?Process.openZygoteSocketIfNeeded銆?/p>
鍚姩 SystemServer
socket 鍒涘缓瀹屾垚涔嬪悗锛岀揣鎺ョ潃灏遍€氳繃 startSystemServer 鍑芥暟鏉ュ惎鍔?SystemServer 杩涚▼銆?/p>
private static boolean startSystemServer(String abiList, String socketName)
{
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 {
parsedArgs = new ZygoteConnection.Arguments(args);
...
/* 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);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
杩欓噷鎴戜滑鍙互浠庡弬鏁版帹娴嬪嚭锛氬垱寤哄悕涓衡€渟ystem_server鈥濈殑杩涚▼锛屽叾鍏ュ彛鏄細 com.android.server.SystemServer 鐨?main 鍑芥暟銆倆ygote 杩涚▼閫氳繃 Zygote.forkSystemServer 鍑芥暟鏉ュ垱寤轰竴涓柊鐨勮繘绋嬫潵鍚姩 SystemServer 缁勪欢锛岃繑鍥炲€?pid 绛?0 鐨勫湴鏂瑰氨鏄柊鐨勮繘绋嬭鎵ц鐨勮矾寰勶紝鍗虫柊鍒涘缓鐨勮繘绋嬩細鎵ц handleSystemServerProcess 鍑芥暟銆俬asSecondZygote 鏄拡瀵?init.zygote64_32.rc锛?init.zygote32_64.rc 杩欎袱鑰呮儏鍐电殑锛屽湪杩欓噷璺宠繃涓嶈皥銆傛帴涓嬫潵鏉ョ湅 handleSystemServerProcess锛?/p>
/**
* 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.
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
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 */
}
handleSystemServerProcess 浼氭姏鍑?MethodAndArgsCaller 寮傚父锛屽墠闈㈡彁鍒拌繖涓紓甯稿叾瀹炴槸澶勭悊姝e父涓氬姟閫昏緫鐨勶紝鐩稿綋浜庝竴涓洖璋冦€傜敱浜庣敱 zygote 杩涚▼鍒涘缓鐨勫瓙杩涚▼浼氱户鎵?zygote 杩涚▼鍦ㄥ墠闈㈠垱寤虹殑 socket 鏂囦欢鎻忚堪绗︼紝鑰岃繖閲岀殑瀛愯繘绋嬪張涓嶄細鐢ㄥ埌瀹冿紝鍥犳锛岃繖閲屽氨璋冪敤 closeServerSocket 鍑芥暟鏉ュ叧闂畠銆係YSTEMSERVERCLASSPATH 鏄寘鍚?/system/framework/framework.jar 鐨勭幆澧冨彉閲忥紝瀹冨畾涔夊湪 system/core/rootdir/init.environ.rc.in 涓細
on init
export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
export ANDROID_BOOTLOGO 1
export ANDROID_ROOT /system
export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH%
export LD_PRELOAD libsigchain.so
handleSystemServerProcess 鍑芥暟鎺ョ潃璋冪敤 RuntimeInit.zygoteInit 鍑芥暟鏉ヨ繘涓€姝ユ墽琛屽惎鍔?SystemServer 缁勪欢鐨勬搷浣溿€?
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}
commonInit 璁剧疆绾跨▼鏈鐞嗗紓甯竓andler锛屾椂鍖虹瓑锛孞NI 鏂规硶 nativeZygoteInit 瀹炵幇鍦?frameworks/base/core/jni/AndroidRuntime.cpp 涓細
static AndroidRuntime* gCurRuntime = NULL;
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
AndroidRuntime 鏄釜甯﹁櫄鍑芥暟鐨勫熀绫伙紝鐪熸鐨勫疄鐜版槸鍦?app_main.cpp 涓殑 AppRuntime:
class AppRuntime : public AndroidRuntime
{
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
}
virtual void onZygoteInit()
{
// Re-enable tracing now that we鈥榬e no longer in Zygote.
atrace_set_tracing_enabled(true);
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
virtual void onExit(int code)
{
if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
}
AndroidRuntime::onExit(code);
}
};
閫氳繃鎵ц AppRuntime::onZygoteInit 鍑芥暟锛岃繖涓繘绋嬬殑 Binder 杩涚▼闂撮€氫俊鏈哄埗鍩虹璁炬柦灏卞噯澶囧ソ浜嗭紝鍙傝€冧唬鐮?frameworks/native/libs/binder/ProcessState.cpp銆?/p>
鎺ヤ笅鏉ワ紝鐪?applicationInit 锛?/p>
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
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鈥榮 static main
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
applicationInit 浠呬粎鏄浆璋?invokeStaticMain锛?/p>
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller
{
Class cl;
cl = Class.forName(className, true, classLoader);
Method m;
m = cl.getMethod("main", new Class[] { String[].class });
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception鈥榮 run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
invokeStaticMain 涔熷緢绠€鍗曪紝閫氳繃鍙嶅皠鎵惧埌鍙傛暟 className 瀵瑰簲鐨勭被鐨勯潤鎬?main 鏂规硶锛岀劧鍚庡皢璇ユ柟娉曚笌鍙傛暟鐢熸垚 ZygoteInit.MethodAndArgsCaller 瀵硅薄褰撳仛寮傚父鎶涘嚭锛岃繖涓紓甯稿璞″湪 ZygoteInit 鐨?main 鍑芥暟琚崟鑾峰苟鎵ц璇ュ璞$殑 run 鏂规硶銆?/p>
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
implements Runnable {
public void run() {
...
mMethod.invoke(null, new Object[] { mArgs });
...
}
}
杩欎箞澶嶆潅鐨勮烦杞紝鍏跺疄灏卞仛浜嗕竴浠剁畝鍗曠殑浜嬫儏锛氭牴鎹?className 鍙嶅皠璋冪敤璇ョ被鐨勯潤鎬?main 鏂规硶銆傝繖涓被鍚嶆槸 ZygoteInit.startSystemServer 鏂规硶涓啓姝荤殑 com.android.server.SystemServer銆?浠庤€岃繘鍏?SystemServer 绫荤殑 main()鏂规硶銆?/p>
鎵ц ZygoteInit.runSelectLoop
鍦?startSystemServer 鍑芥暟涓紝鍒涘缓 system_server 杩涚▼涔嬪悗锛宲id 绛変簬 0 鏃跺湪璇ユ柊杩涚▼涓墽琛?SystemServer.main锛屽惁鍒欏洖鍒?zygote 杩涚▼杩涜鎵ц ZygoteInit.runSelectLoop锛?/p>
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It鈥榮 work that has to be done anyway, and it鈥榮 better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don鈥榯 call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
runSelectLoop鍑芥暟鐨勯€昏緫姣旇緝绠€鍗曪紝涓昏鏈変袱鐐癸細
1銆?澶勭悊瀹㈡埛绔殑杩炴帴鍜岃姹傘€傚墠闈㈠垱寤虹殑 LocalServerSocket 瀵硅薄淇濆瓨 sServerSocket锛岃繖涓?socket 閫氳繃 selectReadable 绛夊緟 ActivityManagerService(绠€鍐?AMS) 涓庝箣閫氫俊銆俿electReadable 鏄竴涓猲ative鍑芥暟锛屽唴閮ㄨ皟鐢╯elect绛夊緟 AMS 杩炴帴锛孉MS 杩炴帴涓婁箣鍚庡氨浼氳繑鍥? 杩斿洖鍊?< 0锛氬唴閮ㄥ彂鐢熼敊璇紱杩斿洖鍊?= 0锛氱涓€娆¤繛鎺ュ埌鏈嶅姟绔?锛涜繑鍥炲€?> 0锛氫笌鏈嶅姟绔凡缁忓缓绔嬭繛鎺ワ紝骞跺紑濮嬪彂閫佹暟鎹€傛瘡涓€涓摼鎺ュ湪 zygote 杩涚▼涓娇鐢?ZygoteConnection 瀵硅薄琛ㄧず銆?/p>
2銆?瀹㈡埛绔殑璇锋眰鐢?ZygoteConnection.runOnce 鏉ュ鐞嗭紝杩欎釜鏂规硶涔熸姏鍑?MethodAndArgsCaller 寮傚父锛屼粠鑰岃繘鍏?MethodAndArgsCaller.run 涓皟鐢ㄦ牴鎹鎴疯姹傛暟鎹弽灏勫嚭鐨勭被鐨?main 鏂规硶銆?/p>
private String[] readArgumentList()
{
int argc;
try {
String s = mSocketReader.readLine();
if (s == null) {
// EOF reached.
return null;
}
argc = Integer.parseInt(s);
} catch (NumberFormatException ex) {
Log.e(TAG, "invalid Zygote wire format: non-int at argc");
throw new IOException("invalid wire format");
}
String[] result = new String[argc];
for (int i = 0; i < argc; i++) {
result[i] = mSocketReader.readLine();
if (result[i] == null) {
// We got an unexpected EOF.
throw new IOException("truncated request");
}
}
return result;
}
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
args = readArgumentList();
parsedArgs = new Arguments(args);
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
...
}
SystemServer 鍚姩杩囩▼
鍦ㄥ墠闈㈠惎鍔?SystemServer涓€鑺傝鍒帮紝閫氳繃鍙嶅皠璋冪敤绫?com.android.server.SystemServer main() 鍑芥暟锛屼粠鑰屽紑濮嬫墽琛?SystemServer 鐨勫垵濮嬪寲娴佺▼銆?/p>
SystemServer.main()
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
main 鍑芥暟鍒涘缓涓€涓?SystemServer 瀵硅薄锛岃皟鐢ㄥ叾 run() 鏂规硶銆?/p>
private void run() {
// If a device鈥榮 clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it shortly.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
} // 妫€娴嬫椂闂磋缃?/span>
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
// property so that it is in sync. We can鈥榯 do this in
// libnativehelper鈥榮 JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
// the property. http://b/11463182
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Enable the sampling profiler.
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
mProfilerSnapshotTimer = new Timer();
mProfilerSnapshotTimer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server", null);
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
} // 鍚姩鎬ц兘鍒嗘瀽閲囨牱
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure
// we鈥榲e defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper(); // 鍑嗗涓荤嚎绋嬪惊鐜?/span>
// Initialize native services.
System.loadLibrary("android_servers");
nativeInit();
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services. // 鍚姩鏈嶅姟
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
// Loop forever.
Looper.loop(); // 鍚姩绾跨▼寰幆锛岀瓑寰呮秷鎭鐞?/span>
throw new RuntimeException("Main thread loop unexpectedly exited");
}
鍦ㄨ繖涓?run 鏂规硶涓紝涓昏瀹屾垚涓変欢浜嬫儏锛屽垱寤?system context 鍜?system service manager锛屽惎鍔ㄤ竴浜涚郴缁熸湇鍔★紝杩涘叆涓荤嚎绋嬫秷鎭惊鐜€?/p>
Zygote 鐨?fork 鏈湴鏂规硶鍒嗘瀽
鎺ヤ笅鏉ユ垜浠粩缁嗗垎鏋?Zygote.forkSystemServer 涓?Zygote.forkAndSpecialize 涓や釜鏂规硶銆?/p>
forkSystemServer
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
VM_HOOKS.postForkCommon();
return pid;
}
鍦ㄨ皟鐢?nativeForkSystemServer 鍒涘缓 system_server 杩涚▼涔嬪墠涓庝箣鍚庯紝閮戒細璋冪敤 ZygoteHooks 杩涜涓€浜涘墠缃笌鍚庣疆澶勭悊銆?/p>
ZygoteHooks.preFork
鍓嶇疆澶勭悊 ZygoteHooks.preFork锛?/p>
public void preFork() {
Daemons.stop();
waitUntilAllThreadsStopped();
token = nativePreFork();
}
Daemons.stop(); 鍋滄铏氭嫙鏈轰腑涓€浜涘畧鎶ょ嚎绋嬫搷浣滐細濡傚紩鐢ㄩ槦鍒椼€佺粓鎺ュ櫒銆丟C绛?/p>
public static void stop() {
ReferenceQueueDaemon.INSTANCE.stop();
FinalizerDaemon.INSTANCE.stop();
FinalizerWatchdogDaemon.INSTANCE.stop();
HeapTrimmerDaemon.INSTANCE.stop();
GCDaemon.INSTANCE.stop();
}
waitUntilAllThreadsStopped 淇濊瘉琚?fork 鐨勮繘绋嬫槸鍗曠嚎绋嬶紝杩欐牱鍙互纭繚閫氳繃 copyonwrite fork 鍑烘潵鐨勮繘绋嬩篃鏄崟绾跨▼锛屼粠鑰岃妭鐪佽祫婧愩€備笌鍓嶉潰鎻愬埌鐨勫湪鏂板缓 system_server 杩涚▼涓皟鐢?closeServerSocket 鍏抽棴 sockect 鏈夊紓鏇插悓宸ヤ箣濡欍€?/p>
/**
* We must not fork until we鈥榬e single-threaded again. Wait until /proc shows we鈥榬e
* down to just one thread.
*/
private static void waitUntilAllThreadsStopped() {
File tasks = new File("/proc/self/task");
while (tasks.list().length > 1) {
try {
// Experimentally, booting and playing about with a stingray, I never saw us
// go round this loop more than once with a 10ms sleep.
Thread.sleep(10);
} catch (InterruptedException ignored) {
}
}
}
鏈湴鏂规硶 nativePreFork 瀹炵幇鍦?art/runtime/native/dalvik_system_ZygoteHooks.cc 涓€?/p>
static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
Runtime* runtime = Runtime::Current();
CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
runtime->PreZygoteFork();
// Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
Thread* self = Thread::Current();
return reinterpret_cast<jlong>(self);
}
ZygoteHooks_nativePreFork 閫氳繃璋冪敤 Runtime::PreZygoteFork 鏉ュ畬鎴?gc 鍫嗙殑涓€浜涘垵濮嬪寲锛岃繖閮ㄥ垎浠g爜鍦?art/runtime/runtime.cc 涓細
heap_ = new gc::Heap(...);
void Runtime::PreZygoteFork() {
heap_->PreZygoteFork();
}
鍒涘缓 system_server 杩涚▼锛?/h4>
nativeForkSystemServer 瀹炵幇鍦?framework/base/core/jni/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) {
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
gSystemServerPid = pid;
// There is a slight window that the system server process has crashed
// but it went unnoticed because we haven鈥榯 published its pid yet. So
// we recheck here just to make sure that all is well.
int status;
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
RuntimeAbort(env);
}
}
return pid;
}
瀹冭浆璋?ForkAndSpecializeCommon 鏉ュ垱寤烘柊杩涚▼锛屽苟纭繚 system_server 鍒涘缓鎴愬姛锛岃嫢涓嶆垚鍔熶究鎴愪粊锛氶噸鍚?zygote锛屽洜涓烘病鏈?system_server 灏卞共涓嶄簡浠€涔堜簨鎯呫€侳orkAndSpecializeCommon 瀹炵幇濡備笅锛?/p>
static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
"(ILjava/lang/String;)V");
// Utility routine to fork zygote and specialize the child process.
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();
pid_t pid = fork();
if (pid == 0) {
// The child process.
...
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
...
UnsetSigChldHandler();
...
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server ? NULL : instructionSet);
}
else if (pid > 0) {
// the parent process
}
return pid;
}
ForkAndSpecializeCommon 棣栧厛璁剧疆瀛愯繘绋嬪紓甯稿鐞唄andler锛岀劧鍚?fork 鏂拌繘绋嬶紝鍦ㄦ柊杩涚▼涓缃?SELinux锛屽苟娓呴櫎瀹冪殑瀛愯繘绋嬪紓甯稿鐞?handler锛岀劧鍚庤皟鐢?Zygote.callPostForkChildHooks 鏂规硶銆?/p>
private static void callPostForkChildHooks(int debugFlags, String instructionSet) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.postForkChild(debugFlags, instructionSet);
checkTime(startTime, "Zygote.callPostForkChildHooks");
}
callPostForkChildHooks 鍙堣浆璋?ZygoteHooks.postForkChild :
public void postForkChild(int debugFlags, String instructionSet) {
nativePostForkChild(token, debugFlags, instructionSet);
}
鏈湴鏂规硶 nativePostForkChild 鍙堣繘鍒?dalvik_system_ZygoteHooks.cc 涓細
static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags,
jstring instruction_set) {
Thread* thread = reinterpret_cast<Thread*>(token);
// Our system thread ID, etc, has changed so reset Thread state.
thread->InitAfterFork();
EnableDebugFeatures(debug_flags);
if (instruction_set != nullptr) {
ScopedUtfChars isa_string(env, instruction_set);
InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
if (isa != kNone && isa != kRuntimeISA) {
action = Runtime::NativeBridgeAction::kInitialize;
}
Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str());
} else {
Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr);
}
}
thread->InitAfterFork(); 瀹炵幇鍦?art/runtime/thread.cc 涓紝璁剧疆鏂拌繘绋嬩富绾跨▼鐨勭嚎绋媔d锛?tid銆侱idForkFromZygote 瀹炵幇鍦?Runtime.cc 涓細
void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) {
is_zygote_ = false;
switch (action) {
case NativeBridgeAction::kUnload:
UnloadNativeBridge();
break;
case NativeBridgeAction::kInitialize:
InitializeNativeBridge(env, isa);
break;
}
// Create the thread pool.
heap_->CreateThreadPool();
StartSignalCatcher();
// Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
// this will pause the runtime, so we probably want this to come last.
Dbg::StartJdwp();
}
棣栧厛鏍规嵁 action 鍙傛暟鏉ュ嵏杞芥垨杞浇鐢ㄤ簬璺ㄥ钩鍙版ˉ鎺ョ敤鐨勫簱銆傜劧鍚庡惎鍔?gc 鍫嗙殑绾跨▼姹犮€係tartSignalCatcher 璁剧疆淇″彿 澶勭悊 handler锛屽叾浠g爜鍦?signal_catcher.cc 涓€?/p>
ZygoteHooks.postForkCommon
鍚庣疆澶勭悊 ZygoteHooks.postForkCommon锛?/p>
public void postForkCommon() {
Daemons.start();
}
postForkCommon 杞皟 Daemons.start锛屼互鍒濆鍖栬櫄鎷熸満涓紩鐢ㄩ槦鍒椼€佺粓鎺ュ櫒浠ュ強 gc 鐨勫畧鎶ょ嚎绋嬨€?/p>
public static void start() {
ReferenceQueueDaemon.INSTANCE.start();
FinalizerDaemon.INSTANCE.start();
FinalizerWatchdogDaemon.INSTANCE.start();
HeapTrimmerDaemon.INSTANCE.start();
GCDaemon.INSTANCE.start();
}
forkAndSpecialize
Zygote.forkAndSpecialize 鏂规硶
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
String instructionSet, String appDataDir) {
long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
instructionSet, appDataDir);
checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
鍓嶇疆澶勭悊涓庡悗缃鐞嗕笌 forkSystemServer 涓竴鏍风殑锛岃繖閲屽氨璺宠繃涓嶈浜嗐€傛湰鍦版柟娉?nativeForkAndSpecialize 瀹炵幇鍦?framework/base/core/jni/com_android_internal_os_Zygote.cpp 涓細
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
// Grant CAP_WAKE_ALARM to the Bluetooth process.
jlong capabilities = 0;
if (uid == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
}
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, instructionSet, appDataDir);
}
杩欎釜鍑芥暟涓?com_android_internal_os_Zygote_nativeForkSystemServer 闈炲父绫讳技锛屽彧涓嶈繃灏戜簡涓€涓‘淇濆瓙杩涚▼鍒涘缓鎴愬姛鐨勬楠ゃ€?/p>
以上是关于Android5 Zygote 涓?SystemServer 鍚姩娴佺▼鍒嗘瀽的主要内容,如果未能解决你的问题,请参考以下文章
Android5 Zygote 与 SystemServer 启动流程分析