android源碼學(xué)習(xí)目錄
1.介紹
zygote進(jìn)程是一個(gè)孵化器,zygote進(jìn)程啟動(dòng)時(shí)會(huì)創(chuàng)建Android 中ART虛擬機(jī)。SystemServer進(jìn)程,應(yīng)用程序進(jìn)程以及運(yùn)行系統(tǒng)的關(guān)鍵服務(wù)進(jìn)程都是通過fock(復(fù)制進(jìn)程)zygote自身來(lái)完成的,所以我們也叫它孵化器進(jìn)程,因?yàn)閟ystemserver等進(jìn)程是通過fock zygote來(lái)完成的,所以zygote中的ART虛擬機(jī)也會(huì)帶入到SystemServer等進(jìn)程。這也就是我們通常所說(shuō)的Android應(yīng)用一個(gè)應(yīng)用一個(gè)虛擬機(jī)。
2.init進(jìn)程對(duì)zygote的啟動(dòng)
上文中我們介紹了init進(jìn)程對(duì)init.rc文件的解析和action的執(zhí)行,zygote是一個(gè)服務(wù),其配置與開始執(zhí)行也是init.rc文件的一部分,它通過import插入到init.rc文件中,根據(jù)不同的系統(tǒng)解析不同的文件,位置在/system/core/rootdir/init.zygotexx.rc, xx是更具不同系統(tǒng)區(qū)分的,有x86有x64, init.zygote64.rc的解析和action一樣,他的解析是通過Parse解析入口添加的ServiceParse類進(jìn)程的,同樣有ServiceManager來(lái)進(jìn)行保存,通過init進(jìn)程main函數(shù) restart_processes(); 來(lái)啟動(dòng)zygote服務(wù)。
2.1zygote服務(wù)配置
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
從上面可以知道 service是通知init進(jìn)程創(chuàng)建名為zygote的進(jìn)程,進(jìn)程路徑為/system/bin/app_process64,下面的為zygote服務(wù)的參數(shù),class為main.
2.2,init進(jìn)程對(duì)zygote的啟動(dòng)
我們知道init.rc解析后會(huì)逐個(gè)執(zhí)行action,init.rc文件中的一個(gè)action有如下配置
on nonencrypted
class_start main //1
class_start late_start
這個(gè)action的command有class_start main,這就是要啟動(dòng)那些classname為main的服務(wù),zygote服務(wù)的classname就為main,所以也會(huì)啟動(dòng)。通過命令與函數(shù)的綁定我們了解action的class_start執(zhí)行的函數(shù)就是/system/core/init/builtins.cpp中的do_class_start函數(shù)。
///system/core/init/builtins.cpp
static int do_class_start(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
return 0;
}
代碼執(zhí)行的邏輯:從ServiceManager保存的所有之前解析的Service表中找到classname為main的服務(wù),讓service執(zhí)行StartNotDisabled()函數(shù)
// /system/core/init/service.cpp
bool Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) { //判斷init.rc配置,init.rc并沒有設(shè)置disabled選項(xiàng)
return Start(); //服務(wù)啟動(dòng)
} else {
flags_ |= SVC_DISABLED_START;
}
return true;
}
更具配置來(lái)判斷是否啟動(dòng)服務(wù),這個(gè)配置啟動(dòng)是是否允許這個(gè)服務(wù)重啟,允許則設(shè)置服務(wù)終止時(shí)會(huì)通過進(jìn)程終止信號(hào)經(jīng)過層層處理找到這個(gè)進(jìn)程,清除這個(gè)進(jìn)程的所有信息,并重啟進(jìn)程。
bool Service::Start() {
// Starting a service removes it from the disabled or reset state and
// immediately takes it out of the restarting state if it was in there.
flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
// Running processes require no additional work --- if they're in the
// process of exiting, we've ensured that they will immediately restart
// on exit, unless they are ONESHOT.
//如果服務(wù)以啟動(dòng)則不做操作。
if (flags_ & SVC_RUNNING) {
return false;
}
bool needs_console = (flags_ & SVC_CONSOLE);
if (needs_console) {
if (console_.empty()) {
console_ = default_console;
}
...
//判斷要啟動(dòng)的service所對(duì)應(yīng)的執(zhí)行文件是否存在,不存在則不執(zhí)行
struct stat sb;
if (stat(args_[0].c_str(), &sb) == -1) {
PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
flags_ |= SVC_DISABLED;
return false;
}
std::string scon;
if (!seclabel_.empty()) {
scon = seclabel_;
} else {
LOG(INFO) << "computing context for service '" << name_ << "'";
scon = ComputeContextFromExecutable(name_, args_[0]);
if (scon == "") {
return false;
}
}
LOG(INFO) << "starting service '" << name_ << "'...";
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork(); //1 重點(diǎn),通過fock來(lái)創(chuàng)建子進(jìn)程,
}
if (pid == 0) {
umask(077);
````
// As requested, set our gid, supplemental gids, uid, context, and
// priority. Aborts on failure.
SetProcessAttributes();
std::vector<char*> strs;
ExpandArgs(args_, &strs);
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) { //2 重點(diǎn),開啟子進(jìn)程執(zhí)行。
PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
}
_exit(127);
}
...
NotifyStateChange("running");
return true;
}
start()函數(shù)比較長(zhǎng),這里我們只關(guān)心幾點(diǎn)就可以,其他的都是一些參數(shù)和console的操作。
- 注釋1處:這里是重點(diǎn),init進(jìn)程啟動(dòng)子進(jìn)程服務(wù)都是通過fock函數(shù)來(lái)創(chuàng)建一個(gè)子進(jìn)程來(lái)完成的,也就是說(shuō)init啟動(dòng)的service都是一個(gè)進(jìn)程,zygote也是一個(gè)進(jìn)成。
- 注釋2處:這里是真正開始執(zhí)行進(jìn)程,也就是告訴這個(gè)進(jìn)程要執(zhí)行什么,也就是zygote進(jìn)程在這里開始執(zhí)行。
init進(jìn)程通過fock后與execve之后就是創(chuàng)建新子進(jìn)程來(lái)執(zhí)行了,也就是說(shuō)下面介紹的--2.3啟動(dòng)zygote過程-- 其實(shí)也是zygote進(jìn)程的一部分,只是沒有執(zhí)行好進(jìn)程的main函數(shù)。
2.3啟動(dòng)zygote過程
execve(strs[0], (char) &strs[0], (char) ENV)函數(shù)主要是init進(jìn)程通過調(diào)動(dòng)app_main.cpp的main函數(shù)中的AppRuntime的start方法來(lái)執(zhí)行啟動(dòng)zygote的,
//位置/framework/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
.... //做了很多配置和參數(shù)操作
while (i < argc) {
const char* arg = argv[i++];
//下面根據(jù)不同的線程設(shè)置不同的標(biāo)記位
if (strcmp(arg, "--zygote") == 0) {
zygote = true; //如果是zygote進(jìn)程,則zygote為true
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; //如果是SystemServer進(jìn)程,則SystemServer為true
} else if (strcmp(arg, "--application") == 0) {
application = true; //如果是application進(jìn)程,則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 (zygote) {
//如果運(yùn)行在zygote進(jìn)程中則通過runtim開始啟動(dòng)進(jìn)程
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
//其他的更具classname來(lái)執(zhí)行進(jìn)程。
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.");
}
這里通過分析組合各個(gè)參數(shù)根據(jù)屬性來(lái)啟動(dòng)這個(gè)進(jìn)程,zygote就是這樣啟動(dòng)的, runtime.start("com.android.internal.os.ZygoteInit", args, zygote);是執(zhí)行的AndroidRuntime.cpp中的代碼。
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
.....
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) { //啟動(dòng)Java虛擬機(jī)
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) { //向Java虛擬機(jī)注冊(cè)JNI方法,這樣才能使Java與c++互調(diào)
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為傳入的參數(shù)為"com.android.internal.os.ZygoteInit",將classname轉(zhuǎn)換為Java中的String 字符串。
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);
}
//替換classnam中的.為/這樣jvm才能識(shí)別。
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到classname中的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 {
//在這里調(diào)用classname的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");
}
AndroidRuntime.start方法做了不少工作,主要的工作就是創(chuàng)建Java虛擬機(jī),注入jni方法,解析參數(shù)classname為jvm能識(shí)別的classname, 找到classname中的main方法并執(zhí)行,這時(shí)我們所熟悉的Java進(jìn)程中的main方法開始執(zhí)行了,也就是zygote的main方法開始執(zhí)行了。