android 重启app_[Boot]Android系统启动-zygote篇
一. 概述
Zygote是由init進(jìn)程通過(guò)解析init.zygote.rc文件而創(chuàng)建的,zygote所對(duì)應(yīng)的可執(zhí)行程序app_process,所對(duì)應(yīng)的源文件是App_main.cpp,進(jìn)程名為zygote。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netdZygote進(jìn)程能夠重啟的地方:
- servicemanager進(jìn)程被殺; (onresart)
- surfaceflinger進(jìn)程被殺; (onresart)
- Zygote進(jìn)程自己被殺; (oneshot=false)
- system_server進(jìn)程被殺; (waitpid)
從App_main()開始,Zygote啟動(dòng)過(guò)程的函數(shù)調(diào)用類大致流程如下:
二、Zygote啟動(dòng)過(guò)程
2.1 App_main.main
[-> App_main.cpp]
int main(int argc, char* const argv[]) {//傳到的參數(shù)argv為“-Xzygote /system/bin --zygote --start-system-server”AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));argc--; argv++; //忽略第一個(gè)參數(shù)int i;for (i = 0; i < argc; i++) {if (argv[i][0] != '-') {break;}if (argv[i][1] == '-' && argv[i][2] == 0) {++i;break;}runtime.addOption(strdup(argv[i]));}//參數(shù)解析bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;++i;while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;//對(duì)于64位系統(tǒng)nice_name為zygote64; 32位系統(tǒng)為zygoteniceName = 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;}}Vector<String8> args;if (!className.isEmpty()) {// 運(yùn)行application或tool程序args.add(application ? String8("application") : String8("tool"));runtime.setClassNameAndArgs(className, argc - i, argv + i);} else {//進(jìn)入zygote模式,創(chuàng)建 /data/dalvik-cache路徑maybeCreateDalvikCache();if (startSystemServer) {args.add(String8("start-system-server"));}char prop[PROP_VALUE_MAX];if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {return 11;}String8 abiFlag("--abi-list=");abiFlag.append(prop);args.add(abiFlag);for (; i < argc; ++i) {args.add(String8(argv[i]));}}//設(shè)置進(jìn)程名if (!niceName.isEmpty()) {runtime.setArgv0(niceName.string());set_process_name(niceName.string());}if (zygote) {// 啟動(dòng)AppRuntime 【見小節(jié)2.2】runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} else {//沒有指定類名或zygote,參數(shù)錯(cuò)誤return 10;} }2.2 start
[-> AndroidRuntime.cpp]
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {static const String8 startSystemServer("start-system-server");for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {const int LOG_BOOT_PROGRESS_START = 3000;}}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {return;}setenv("ANDROID_ROOT", rootDir, 1);}JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;// 虛擬機(jī)創(chuàng)建【見小節(jié)2.3】if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);// JNI方法注冊(cè)【見小節(jié)2.4】if (startReg(env) < 0) {return;}jclass stringClass;jobjectArray strArray;jstring classNameStr;//等價(jià) strArray= new String[options.size() + 1];stringClass = env->FindClass("java/lang/String");strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);//等價(jià) strArray[0] = "com.android.internal.os.ZygoteInit"classNameStr = env->NewStringUTF(className);env->SetObjectArrayElement(strArray, 0, classNameStr);//等價(jià) strArray[1] = "start-system-server";// strArray[2] = "--abi-list=xxx";//其中xxx為系統(tǒng)響應(yīng)的cpu架構(gòu)類型,比如arm64-v8a.for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());env->SetObjectArrayElement(strArray, i + 1, optionsStr);}//將"com.android.internal.os.ZygoteInit"轉(zhuǎn)換為"com/android/internal/os/ZygoteInit"char* slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {...} else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");// 調(diào)用ZygoteInit.main()方法【見小節(jié)3.1】env->CallStaticVoidMethod(startClass, startMeth, strArray);}//釋放相應(yīng)對(duì)象的內(nèi)存空間free(slashClassName);mJavaVM->DetachCurrentThread();mJavaVM->DestroyJavaVM(); }2.3 startVm
[–> AndroidRuntime.cpp]
創(chuàng)建Java虛擬機(jī)方法的主要篇幅是關(guān)于虛擬機(jī)參數(shù)的設(shè)置,下面只列舉部分在調(diào)試優(yōu)化過(guò)程中常用參數(shù)。
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) {// JNI檢測(cè)功能,用于native層調(diào)用jni函數(shù)時(shí)進(jìn)行常規(guī)檢測(cè),比較弱字符串格式是否符合要求,資源是否正確釋放。該功能一般用于早期系統(tǒng)調(diào)試或手機(jī)Eng版,對(duì)于User版往往不會(huì)開啟,引用該功能比較消耗系統(tǒng)CPU資源,降低系統(tǒng)性能。bool checkJni = false;property_get("dalvik.vm.checkjni", propBuf, "");if (strcmp(propBuf, "true") == 0) {checkJni = true;} else if (strcmp(propBuf, "false") != 0) {property_get("ro.kernel.android.checkjni", propBuf, "");if (propBuf[0] == '1') {checkJni = true;}}if (checkJni) {addOption("-Xcheck:jni");}//虛擬機(jī)產(chǎn)生的trace文件,主要用于分析系統(tǒng)問題,路徑默認(rèn)為/data/anr/traces.txtparseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");//對(duì)于不同的軟硬件環(huán)境,這些參數(shù)往往需要調(diào)整、優(yōu)化,從而使系統(tǒng)達(dá)到最佳性能parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");parseRuntimeOption("dalvik.vm.heaptargetutilization",heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");...//preloaded-classes文件內(nèi)容是由WritePreloadedClassFile.java生成的,//在ZygoteInit類中會(huì)預(yù)加載工作將其中的classes提前加載到內(nèi)存,以提高系統(tǒng)性能if (!hasFile("/system/etc/preloaded-classes")) {return -1;}//初始化虛擬機(jī)if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failedn");return -1;} }2.4 startReg
[–> AndroidRuntime.cpp]
int AndroidRuntime::startReg(JNIEnv* env) {//設(shè)置線程創(chuàng)建方法為javaCreateThreadEtc 【見小節(jié)2.4.1】androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);env->PushLocalFrame(200);//進(jìn)程N(yùn)I方法的注冊(cè)【見小節(jié)2.4.2】if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);return 0; }2.4.1 androidSetCreateThreadFunc
[-> Threads.cpp]
void androidSetCreateThreadFunc(android_create_thread_fn func) {gCreateThreadFn = func; }虛擬機(jī)啟動(dòng)后startReg()過(guò)程,會(huì)設(shè)置線程創(chuàng)建函數(shù)指針gCreateThreadFn指向javaCreateThreadEtc.
2.4.2 register_jni_procs
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) {for (size_t i = 0; i < count; i++) {//【見小節(jié)2.4.3】if (array[i].mProc(env) < 0) {return -1;}}return 0; }2.4.3 gRegJNI.mProc
static const RegJNIRec gRegJNI[] = {REG_JNI(register_com_android_internal_os_RuntimeInit),REG_JNI(register_android_os_Binder),... };array[i]是指gRegJNI數(shù)組, 該數(shù)組有100多個(gè)成員。其中每一項(xiàng)成員都是通過(guò)REG_JNI宏定義的:
#define REG_JNI(name) { name } struct RegJNIRec {int (*mProc)(JNIEnv*); };可見,調(diào)用mProc,就等價(jià)于調(diào)用其參數(shù)名所指向的函數(shù)。 例如REG_JNI(register_com_android_internal_os_RuntimeInit).mProc也就是指進(jìn)入register_com_android_internal_os_RuntimeInit方法,接下來(lái)就繼續(xù)以此為例來(lái)說(shuō)明:
int register_com_android_internal_os_RuntimeInit(JNIEnv* env) {return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",gMethods, NELEM(gMethods)); }//gMethods:java層方法名與jni層的方法的一一映射關(guān)系 static JNINativeMethod gMethods[] = {{ "nativeFinishInit", "()V",(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },{ "nativeZygoteInit", "()V",(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },{ "nativeSetExitWithoutCleanup", "(Z)V",(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup }, };三. 進(jìn)入Java層
前面[小節(jié)2.2]AndroidRuntime.start()執(zhí)行到最后通過(guò)反射調(diào)用到ZygoteInit.main(),見下文:
3.1 ZygoteInit.main
[–>ZygoteInit.java]
public static void main(String argv[]) {try {RuntimeInit.enableDdms(); //開啟DDMS功能SamplingProfilerIntegration.start();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]);}}...registerZygoteSocket(socketName); //為Zygote注冊(cè)socket【見小節(jié)3.2】preload(); // 預(yù)加載類和資源【見小節(jié)3.3】SamplingProfilerIntegration.writeZygoteSnapshot();gcAndFinalize(); //GC操作if (startSystemServer) {startSystemServer(abiList, socketName);//啟動(dòng)system_server【見小節(jié)3.4】}runSelectLoop(abiList); //進(jìn)入循環(huán)模式【見小節(jié)3.5】closeServerSocket();} catch (MethodAndArgsCaller caller) {caller.run(); //啟動(dòng)system_server中會(huì)講到。} catch (RuntimeException ex) {closeServerSocket();throw ex;} }在異常捕獲后調(diào)用的方法caller.run(),會(huì)在后續(xù)的system_server文章會(huì)講到。
3.2 registerZygoteSocket
[–>ZygoteInit.java]
private static void registerZygoteSocket(String socketName) {if (sServerSocket == null) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;try {String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {...}try {FileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc); //設(shè)置文件描述符sServerSocket = new LocalServerSocket(fd); //創(chuàng)建Socket的本地服務(wù)端} catch (IOException ex) {...}} }3.3 preload
[–>ZygoteInit.java]
static void preload() {//預(yù)加載位于/system/etc/preloaded-classes文件中的類preloadClasses();//預(yù)加載資源,包含drawable和color資源preloadResources();//預(yù)加載OpenGLpreloadOpenGL();//通過(guò)System.loadLibrary()方法,//預(yù)加載"android","compiler_rt","jnigraphics"這3個(gè)共享庫(kù)preloadSharedLibraries();//預(yù)加載 文本連接符資源preloadTextResources();//僅用于zygote進(jìn)程,用于內(nèi)存共享的進(jìn)程WebViewFactory.prepareWebViewInZygote(); }執(zhí)行Zygote進(jìn)程的初始化,對(duì)于類加載,采用反射機(jī)制Class.forName()方法來(lái)加載。對(duì)于資源加載,主要是 com.android.internal.R.array.preloaded_drawables和com.android.internal.R.array.preloaded_color_state_lists,在應(yīng)用程序中以http://com.android.internal.R.xxx開頭的資源,便是此時(shí)由Zygote加載到內(nèi)存的。
zygote進(jìn)程內(nèi)加載了preload()方法中的所有資源,當(dāng)需要fork新進(jìn)程時(shí),采用copy on write技術(shù),如下:
3.4 startSystemServer
[–>ZygoteInit.java]
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);//參數(shù)準(zhǔn)備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 {//用于解析參數(shù),生成目標(biāo)格式parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);// fork子進(jìn)程,用于運(yùn)行system_serverpid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}//進(jìn)入子進(jìn)程system_serverif (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}// 完成system_server進(jìn)程剩余的工作handleSystemServerProcess(parsedArgs);}return true; }準(zhǔn)備參數(shù)并fork新進(jìn)程,從上面可以看出system server進(jìn)程參數(shù)信息為uid=1000,gid=1000,進(jìn)程名為sytem_server,從zygote進(jìn)程fork新進(jìn)程后,需要關(guān)閉zygote原有的socket。另外,對(duì)于有兩個(gè)zygote進(jìn)程情況,需等待第2個(gè)zygote創(chuàng)建完成。更多詳情見Android系統(tǒng)啟動(dòng)-systemServer上篇。
3.5 runSelectLoop
[–>ZygoteInit.java]
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();//sServerSocket是socket通信中的服務(wù)端,即zygote進(jìn)程。保存到fds[0]fds.add(sServerSocket.getFileDescriptor());peers.add(null);while (true) {StructPollfd[] pollFds = new StructPollfd[fds.size()];for (int i = 0; i < pollFds.length; ++i) {pollFds[i] = new StructPollfd();pollFds[i].fd = fds.get(i);pollFds[i].events = (short) POLLIN;}try {//處理輪詢狀態(tài),當(dāng)pollFds有事件到來(lái)則往下執(zhí)行,否則阻塞在這里Os.poll(pollFds, -1);} catch (ErrnoException ex) {...}for (int i = pollFds.length - 1; i >= 0; --i) {//采用I/O多路復(fù)用機(jī)制,當(dāng)接收到客戶端發(fā)出連接請(qǐng)求 或者數(shù)據(jù)處理請(qǐng)求到來(lái),則往下執(zhí)行;// 否則進(jìn)入continue,跳出本次循環(huán)。if ((pollFds[i].revents & POLLIN) == 0) {continue;}if (i == 0) {//即fds[0],代表的是sServerSocket,則意味著有客戶端連接請(qǐng)求;// 則創(chuàng)建ZygoteConnection對(duì)象,并添加到fds。ZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor()); //添加到fds.} else {//i>0,則代表通過(guò)socket接收來(lái)自對(duì)端的數(shù)據(jù),并執(zhí)行相應(yīng)操作【見小節(jié)3.6】boolean done = peers.get(i).runOnce();if (done) {peers.remove(i);fds.remove(i); //處理完則從fds中移除該文件描述符}}}} }Zygote采用高效的I/O多路復(fù)用機(jī)制,保證在沒有客戶端連接請(qǐng)求或數(shù)據(jù)處理時(shí)休眠,否則響應(yīng)客戶端的請(qǐng)求。
3.6 runOnce
[-> ZygoteConnection.java]
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {String args[];Arguments parsedArgs = null;FileDescriptor[] descriptors;try {//讀取socket客戶端發(fā)送過(guò)來(lái)的參數(shù)列表args = readArgumentList();descriptors = mSocket.getAncillaryFileDescriptors();} catch (IOException ex) {...return true;}...try {//將binder客戶端傳遞過(guò)來(lái)的參數(shù),解析成Arguments對(duì)象格式parsedArgs = new Arguments(args);...//【見小節(jié)7】pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);} catch (Exception e) {...}try {if (pid == 0) {//子進(jìn)程執(zhí)行IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;//進(jìn)入子進(jìn)程流程handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);return true;} else {//父進(jìn)程執(zhí)行IoUtils.closeQuietly(childPipeFd);childPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);} }更多內(nèi)容,見理解Android進(jìn)程創(chuàng)建流程
四、總結(jié)
Zygote啟動(dòng)過(guò)程的調(diào)用流程圖:
最后,介紹給通過(guò)cmd命令,來(lái)fork新進(jìn)程來(lái)執(zhí)行類中main方法的方式:(啟動(dòng)后進(jìn)入RuntimeInit.main)
app_process [可選參數(shù)] 命令所在路徑 啟動(dòng)的類名 [可選參數(shù)]總結(jié)
以上是生活随笔為你收集整理的android 重启app_[Boot]Android系统启动-zygote篇的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 调用另一个类的方法_一个隐藏在方法
- 下一篇: redis 一般启动几个 哨兵_Redi