編輯:關於Android編程
前面的文章花了很大的篇幅去介紹了init進程如何去解析init.rc,如何去執行系統的一些服務。
那麼,我們所說的zygote是怎麼啟動的呢?zygote又是具體負責了哪些工作呢?
本文我們來一探究竟。
zygote在inir.rc中有如下的描述:
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
我們可以簡單的分析下這兩句話,
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
這個是說,zygote是屬於main的class。
zygote是一個服務,服務的名字叫zygote. 啟動的時候執行的命令是app_process, 傳遞的參數是-Xzygote /system/bin --zygote --start-system-server
那麼,按照我們前面分析的理論,我們去看一下app_process是個什麼東西
首先我們到framework的目錄下,在base/cmds/app_process裡面,我們看到了生成app_process的makefile
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=
app_main.cpp
LOCAL_SHARED_LIBRARIES :=
libcutils
libutils
liblog
libbinder
libandroid_runtime
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
我們可以看到app_process被執行生成了一個應用程序。
試想一下,zygote的這個服務應該是一直在運行的,但是我們如果adb shell去看ps的話,並找不到app_process的這個命令在一直運行。
這個是為什麼呢?
首先我們從app_process的main函數裡面截取出來一段
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, --zygote) == 0) { // 如果從init.rc裡面傳進來的參數是帶--zygote的話,一定是會進這個判斷
zygote = true; // 將zygote設置為true
niceName = ZYGOTE_NICE_NAME; // 將niceName設置為zygote_nice_name設置為zygote
} else if (strcmp(arg, --start-system-server) == 0) { // 如果是要啟動start-system-server的話
startSystemServer = true; // 會將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;
}
}
然後這幾個參數可以怎麼去使用呢?
接著看一下後面的代碼,是如何使用的。
if (!niceName.isEmpty()) { //如果niceName不為空的話
runtime.setArgv0(niceName.string());
set_process_name(niceName.string()); // 調用這個函數將這個process的name設置為zygote
}
if (zygote) { // zygote一定為true
runtime.start(com.android.internal.os.ZygoteInit, args); //我們進入到了這個判斷
} else if (className) {
runtime.start(com.android.internal.os.RuntimeInit, args);
} else {
fprintf(stderr, Error: no class name or --zygote supplied.
);
app_usage();
LOG_ALWAYS_FATAL(app_process: no class name or --zygote supplied.);
return 10;
}
我們可以看到,runtime是調用了start的方法區進行了這個zygote的啟動的工作,那麼我們這個runtime是調用的哪邊的start呢?
我們在當前的appruntime裡面,是沒有相關start函數的實現。
那我們去他的父類裡面去看一下。
class AppRuntime : public AndroidRuntimeandroidruntime是怎麼樣的呢?裡面有沒有start的方法呢?
AndroidRunTime的實現位於:frameworks/base/core/jni/AndroidRuntime.cpp
我們從裡面找到了start的方法。
951void AndroidRuntime::start(const char* className, const Vector來根據剛才傳遞的參數來看一下zygoteInit的main函數& options) 952{ 953 ALOGD(>>>>>> START %s uid %d <<<<<< , 954 className != NULL ? className : (unknown), getuid()); 955 956 static const String8 startSystemServer(start-system-server); 957 958 /* 959 * 'startSystemServer == true' means runtime is obsolete and not run from 960 * init.rc anymore, so we print out the boot start event here. 961 */ 962 for (size_t i = 0; i < options.size(); ++i) { 963 if (options[i] == startSystemServer) { 964 /* track our progress through the boot sequence */ 965 const int LOG_BOOT_PROGRESS_START = 3000; 966 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); 967 } 968 } 969 970 const char* rootDir = getenv(ANDROID_ROOT); 971 if (rootDir == NULL) { 972 rootDir = /system; 973 if (!hasDir(/system)) { 974 LOG_FATAL(No root directory specified, and /android does not exist.); 975 return; 976 } 977 setenv(ANDROID_ROOT, rootDir, 1); 978 } 979 980 //const char* kernelHack = getenv(LD_ASSUME_KERNEL); 981 //ALOGD(Found LD_ASSUME_KERNEL='%s' , kernelHack); 982 983 /* start the virtual machine */ 984 JniInvocation jni_invocation; 985 jni_invocation.Init(NULL); 986 JNIEnv* env; 987 if (startVm(&mJavaVM, &env) != 0) { // 創建虛擬機 988 return; 989 } 990 onVmCreated(env); 991 992 /* 993 * Register android functions. 994 */ 995 if (startReg(env) < 0) { // 注冊jni的方法 996 ALOGE(Unable to register all android natives ); 997 return; 998 } 999 1000 /* 1001 * We want to call main() with a String array with arguments in it. 1002 * At present we have two arguments, the class name and an option string. 1003 * Create an array to hold them. 1004 */ 1005 jclass stringClass; // class對象 1006 jobjectArray strArray; // 對應objectArray對象 1007 jstring classNameStr; // 一個string 1008 1009 stringClass = env->FindClass(java/lang/String); //首先找到了string的class 1010 assert(stringClass != NULL); 1011 strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); // New 了一個ObjectArray 1012 assert(strArray != NULL); 1013 classNameStr = env->NewStringUTF(className); // 將className轉換為UTF8的類型 1014 assert(classNameStr != NULL); 1015 env->SetObjectArrayElement(strArray, 0, classNameStr); // 設置objectarray的第一個元素為classname 1016 1017 for (size_t i = 0; i < options.size(); ++i) { // 將後續的參數依次經過轉換push到strArray的數組中 1018 jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); 1019 assert(optionsStr != NULL); 1020 env->SetObjectArrayElement(strArray, i + 1, optionsStr); 1021 } 1022 1023 /* 1024 * Start VM. This thread becomes the main thread of the VM, and will 1025 * not return until the VM exits. 1026 */ 1027 char* slashClassName = toSlashClassName(className); // 將className轉換為/的形式 1028 jclass startClass = env->FindClass(slashClassName); // 尋找這個類 1029 if (startClass == NULL) { // 如果找不到的話,我們會返回NULL 1030 ALOGE(JavaVM unable to locate class '%s' , slashClassName); 1031 /* keep going */ 1032 } else { 1033 jmethodID startMeth = env->GetStaticMethodID(startClass, main, 1034 ([Ljava/lang/String;)V); // 獲取我們尋找到的這個類的main函數 1035 if (startMeth == NULL) { 1036 ALOGE(JavaVM unable to find main() in '%s' , className); 1037 /* keep going */ 1038 } else { 1039 env->CallStaticVoidMethod(startClass, startMeth, strArray); // 去執行這個類的main函數的方法。 1040 1041#if 0 1042 if (env->ExceptionCheck()) 1043 threadExitUncaughtException(env); 1044#endif 1045 } 1046 } 1047 free(slashClassName); // free 1048 1049 ALOGD(Shutting down VM ); 1050 if (mJavaVM->DetachCurrentThread() != JNI_OK) 1051 ALOGW(Warning: unable to detach main thread ); 1052 if (mJavaVM->DestroyJavaVM() != 0) 1053 ALOGW(Warning: VM did not shut down cleanly ); 1054}
648 public static void main(String argv[]) {
649 try {
650 // Start profiling the zygote initialization.
651 SamplingProfilerIntegration.start();
652
653 boolean startSystemServer = false;
654 String socketName = zygote;
655 String abiList = null;
656 for (int i = 1; i < argv.length; i++) {
657 if (start-system-server.equals(argv[i])) {
658 startSystemServer = true; // startSystemServer為true
659 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
660 abiList = argv[i].substring(ABI_LIST_ARG.length());
661 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
662 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
663 } else {
664 throw new RuntimeException(Unknown command line argument: + argv[i]);
665 }
666 }
667
668 if (abiList == null) {
669 throw new RuntimeException(No ABI list supplied.);
670 }
671
672 registerZygoteSocket(socketName); // 注冊了一個socket,用來與系統中的其他應用程序進行通信
673 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
674 SystemClock.uptimeMillis());
675 preload(); // 預加載一些資源
676 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
677 SystemClock.uptimeMillis());
678
679 // Finish profiling the zygote initialization.
680 SamplingProfilerIntegration.writeZygoteSnapshot();
681
682 // Do an initial gc to clean up after startup
683 gc();
684
685 // Disable tracing so that forked processes do not inherit stale tracing tags from
686 // Zygote.
687 Trace.setTracingEnabled(false);
688
689 if (startSystemServer) { // 如果startSystemServer為true的話,我們會啟動systemServer
690 startSystemServer(abiList, socketName);
691 }
692
693 Log.i(TAG, Accepting command socket connections);
694 runSelectLoop(abiList); // 進入select的循環,用來響應其他應用程序的請求
695
696 closeServerSocket();
697 } catch (MethodAndArgsCaller caller) {
698 caller.run();
699 } catch (RuntimeException ex) {
700 Log.e(TAG, Zygote died with exception, ex);
701 closeServerSocket();
702 throw ex;
703 }
704 }
那麼,最後我們對zygote進行一下總結
首先zygote創建了appruntime的對象,並調用他的start。此後的活動由AppRuntime來控制
然後調用startVM來創建了虛擬機,調用startReg來注冊JNI的函數
通過JNI調用zygoteInit進入了java的世界
調用registerZygoteSocket來響應子孫後代的請求,同時調用preload函數進行資源的預加載
調用startSystemServer來進行系統啟動的後續工作
完成了java世界的初創工作後,變進入了select循環,來處理後續的請求。
小米5、榮耀V8、魅族PRO6和一加手機3哪個好 參數對比評測
國產手機的集體高潮,卻使消費者變的“煩惱了”,因為消費者在購買手機時變得越來越猶豫糾結。以2499元這個價位的手機來說,單國產手機就
android adb使用
#####################################################################################
Android中BroadCast與Activity之間的通信
在看本文之前,如果你對於Android的廣播機制不是很了解,建議先行閱讀我轉載的一篇博文:圖解 Android 廣播機制。 由於本案例比較簡單,故直接在此貼出代碼,不做
Android自定義View—滑動控件
MainActivity如下:package cc.testview4; import cc.testview4.SlideView.SwitchChangedList