事先宣告本文為作者本人記錄學習使用
其中部分文字或者技術觀點摘自https://blog.csdn.net/marshal_zsx/article/details/80547780 這里推薦此作者文章
zygote行程主要負責創建Java虛擬機,加載系統資源,啟動SystemServer行程,以及在后續運行程序中啟動普通的應用程式,
init.rc AOSP/system/core/rootdir/init.rc
//部分代碼截取
...
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
...
這里的 import /init.${ro.zygote}.rc 匯入的就是 init.zygote64.rc
init.zygote64.rc AOSP/system/core/rootdir/init.zygote64.rc
行程名稱是zygote,運行的二進制檔案在/system/bin/app_process64 啟動引數是 -Xzygote /system/bin --zygote --start-system-server
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
main(int argc, char** argv) AOSP/system/core/rootdir/init.cpp
在init行程的最后,會加入 late-init 的trigger
...
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
...
init.rc AOSP/system/core/rootdir/init.rc
而當 on late-init 觸發時會觸發trigger zygote-start
on late-init
...
# Now we can start zygote for devices with file based encryption
trigger zygote-start
...
當zygote-start 觸發時,會執行以下操作
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=unsupported
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
AOSP/system/core/init/builtins.cpp
start 命令有一個對應的執行函式 do_start
static const Map builtin_functions = {
...
{"setrlimit", {3, 3, do_setrlimit}},
{"start", {1, 1, do_start}},
{"stop", {1, 1, do_stop}},
...
};
do_start首先是通過FindServiceByName去service陣列中遍歷,根據名字匹配出對應的service,然后呼叫service的Start函式,Start函式我們在上一篇結尾有分析,主要是fork出一個新行程然后執行service對應的二進制檔案,并將引數傳遞進去.
static int do_start(const std::vector<std::string>& args) {
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);//找出對應service
if (!svc) {
LOG(ERROR) << "do_start: Service " << args[1] << " not found";
return -1;
}
if (!svc->Start()) //呼叫start
return -1;
return 0;
}
Android.mk AOSP/frameworks/base/cmds/app_process/Android.mk
zygote對應的二進制檔案是 /system/bin/app_process64 ,app_process、app_process32、app_process64,對應的源檔案都是app_main.cpp.
app_process_src_files := \
app_main.cpp \
...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
main() AOSP/frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
//將引數argv放到argv_String字串中,然后列印出來
//之前start zygote傳入的引數是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[i]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//構建AppRuntime物件,并將引數傳入
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.
//
// As an exception to the above rule, anything in "spaced commands"
// goes to the vm even though it has a space in it.
//上面這段英文大概講的是,所有在 "--" 后面的非 "-"開頭的引數都將傳入vm, 但是有個例外是spaced commands陣列中的引數
const char* spaced_commands[] = { "-cp", "-classpath" };//這兩個引數是Java程式需要依賴的Jar包,相當于import
// Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
bool known_command = false;
int i;
for (i = 0; i < argc; i++) {
if (known_command == true) { //將spaced_commands中的引數額外加入VM
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add known option '%s'", argv[i]);
known_command = false;
continue;
}
for (int j = 0;
j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
if (strcmp(argv[i], spaced_commands[j]) == 0) {//比較引數是否是spaced_commands中的引數
known_command = true;
ALOGV("app_process main found known command '%s'", argv[i]);
}
}
if (argv[i][0] != '-') { //如果引數第一個字符是'-',直接跳出回圈,之前傳入的第一個引數是 -Xzygote,所以執行到這兒就跳出了,i=0
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add option '%s'", argv[i]);
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
//跳過一個引數,之前跳過了-Xzygote,這里繼續跳過 /system/bin ,也就是所謂的 "parent dir"
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {//表示是zygote啟動模式
zygote = true;
niceName = ZYGOTE_NICE_NAME;//這個值根據平臺可能是zygote64或zygote
} else if (strcmp(arg, "--start-system-server") == 0) {//需要啟動SystemServer
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {//表示是application啟動模式,也就是普通應用程式
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {//行程別名
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {//application啟動的class
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector<String8> args;
if (!className.isEmpty()) {//className不為空,說明是application啟動模式
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);//將className和引數設定給runtime
if (!LOG_NDEBUG) {//列印class帶的引數
String8 restOfArgs;
char* const* argv_new = argv + i;
int argc_new = argc - i;
for (int k = 0; k < argc_new; ++k) {
restOfArgs.append("\"");
restOfArgs.append(argv_new[k]);
restOfArgs.append("\" ");
}
ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
}
} else { //zygote啟動模式
// We're in zygote mode.
maybeCreateDalvikCache(); //新建Dalvik的快取目錄
if (startSystemServer) {//加入start-system-server引數
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag); //加入--abi-list=引數
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {//將剩下的引數加入args
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {//設定行程別名
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) { //如果是zygote啟動模式,則加載ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {//如果是application啟動模式,則加載RuntimeInit
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
最后呼叫的是runtime.start函式,這個就是要啟動虛擬機了,接下來我們分析start函式
start() AOSP/frameworks/base/core/jni/AndroidRuntime.cpp 看注釋
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { //創建java虛擬機
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) { //為java虛擬機注冊jni方法
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
//className 為 com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
//com.android.internal.os.ZygoteInit 把“.”替換為“/”
char* slashClassName = toSlashClassName(className != NULL ? className : "");
//找到ZygoteInit
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
//呼叫main
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
由此又c++層呼叫到了java層
main() AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
【1】創建server端的socket這個名為zygote的Socket用于等待AMS請求zygote來創建新的應用程式行程
【2】等待AMS建新的應用程式行程
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
...
//創建server端的socket【1】
zygoteServer.registerServerSocket(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//預加載類和資源
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
if (startSystemServer) {
//啟動SystemServer
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//【2】
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
registerServerSocket() AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
在這創建的socket
void registerServerSocket(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/280721.html
標籤:其他
