

1、Loader
Loader層首先就是Boot ROM,當(dāng)手機(jī)處于關(guān)機(jī)狀態(tài)時(shí),長(zhǎng)按電源鍵開機(jī),引導(dǎo)芯片從固化在ROM里的預(yù)設(shè)代碼開始執(zhí)行,然后機(jī)制引導(dǎo)程序到RAM中。
而Boot Loader就是引導(dǎo)程序,主要是檢查RAM,初始化硬件參數(shù)等功能。
Linux內(nèi)核層前面我們知道Android系統(tǒng)是基于Linux內(nèi)核,而這時(shí)會(huì)啟動(dòng)Linux內(nèi)核的倆個(gè)主要進(jìn)程:
2、Kernel
啟動(dòng)Kernel的swapper進(jìn)程(pid=0),該進(jìn)程又稱為是idle進(jìn)程,是Kernel由無(wú)到有的第一個(gè)進(jìn)程,用于初始化進(jìn)程管理、內(nèi)存管理,加載Display、Camera Driver、Binder Driver等工作。
啟動(dòng)kthreadd進(jìn)程(pid=2),該進(jìn)程是Linux系統(tǒng)的內(nèi)核進(jìn)程,會(huì)創(chuàng)建內(nèi)核工作線程kworkder,軟中斷線程ksoftirqd等內(nèi)核守護(hù)進(jìn)程。kthreadd進(jìn)程是所有內(nèi)核進(jìn)程的鼻祖。
3、C++ Framework
Native層上面所說(shuō)的都是Linux內(nèi)核進(jìn)程,而到Native層會(huì)創(chuàng)建init進(jìn)程(pid=1),該進(jìn)程是用戶進(jìn)程,也是所有用戶進(jìn)程的鼻祖。
init進(jìn)程的主要作用:
init進(jìn)程會(huì)孵化出ueventd、logd、installd、adbd等用戶守護(hù)進(jìn)程(系統(tǒng)必需的一些服務(wù))。
init進(jìn)程還會(huì)啟動(dòng)servicemanager(binder服務(wù)管家)、bootanim開機(jī)動(dòng)畫等重要服務(wù)。
init進(jìn)程還會(huì)孵化出用來(lái)管理C++ Framework庫(kù)的Media Server進(jìn)程。
init進(jìn)程會(huì)孵化出Zygote進(jìn)程,Zygote進(jìn)程是Android系統(tǒng)第一個(gè)Java進(jìn)程(虛擬機(jī)進(jìn)程),所以Zygote是所有Java進(jìn)程的父進(jìn)程。
而這里Native層和Linux內(nèi)核層的通信是利用系統(tǒng)調(diào)用,關(guān)于系統(tǒng)調(diào)用簡(jiǎn)單來(lái)說(shuō)就是Linux內(nèi)核為了防止用戶態(tài)的程序隨意調(diào)用內(nèi)核代碼導(dǎo)致內(nèi)核掛掉,所有想使用內(nèi)核的服務(wù)都必須通過(guò)系統(tǒng)調(diào)用。
這里有一些同學(xué)之前認(rèn)為C++層的代碼就是內(nèi)核層,其實(shí)不是的,真正內(nèi)核層的只有Linux內(nèi)核層,Native層是用戶態(tài)的C/C++實(shí)現(xiàn)部分。
Java Framework層Zygote進(jìn)程是由init進(jìn)程通過(guò)解析init.rc后fork而來(lái),由Zygote進(jìn)程開啟Java世界,主要包括:
4、Framework
加載ZygoteInit類,注冊(cè)Zygote Socket服務(wù)端套接字,這個(gè)是為了響應(yīng)后面fork新進(jìn)程的需求。
加載虛擬機(jī),即創(chuàng)建ART虛擬機(jī)。
預(yù)加載類preloadClass。
預(yù)加載資源preloadResources。
然后Zygote進(jìn)程還會(huì)孵化出System Server進(jìn)程,該進(jìn)程同時(shí)也是Zygote孵化的第一個(gè)進(jìn)程,該進(jìn)程非常熟悉了,它管理著Java framework,包括AMS、WMS等各種服務(wù)。
這里有個(gè)非常重要的點(diǎn),就說(shuō)JNI技術(shù),通過(guò)JNI技術(shù)打通了Java世界和C/C++世界。
5、APPS
應(yīng)用層Zygote進(jìn)程會(huì)孵化出第一個(gè)APP進(jìn)程就是Launcher了,即桌面APP,每個(gè)APP至少運(yùn)行在一個(gè)進(jìn)程上,而這些進(jìn)程都是由Zygote進(jìn)程孵化而來(lái)。
經(jīng)過(guò)上面的流程梳理,我們更可以發(fā)現(xiàn)Android系統(tǒng)設(shè)計(jì)的巧妙,每一層都有對(duì)應(yīng)的作用,都由相應(yīng)的進(jìn)程來(lái)管理,我們可以通過(guò)Linux的ps命令來(lái)簡(jiǎn)單查看當(dāng)前系統(tǒng)的所有進(jìn)程。
C++ Framework
Linux 內(nèi)核啟動(dòng)過(guò)程中會(huì)創(chuàng)建 init 進(jìn)程,init 進(jìn)程是用戶空間的第一個(gè)進(jìn)程(pid=1),對(duì)應(yīng)的可執(zhí)行程序的源文件文件為 它的 main 方法如下:
[/system/core/init/Main.cpp]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "builtins.h"
#include "first_stage_init.h"
#include "init.h"
#include "selinux.h"
#include "subcontext.h"
#include "ueventd.h"
#include <android-base/logging.h>
#if __has_feature(address_sanitizer)
#include <sanitizer/asan_interface.h>
#endif
#if __has_feature(address_sanitizer)
// Load asan.options if it exists since these are not yet in the environment.
// Always ensure detect_container_overflow=0 as there are false positives with this check.
// Always ensure abort_on_error=1 to ensure we reboot to bootloader for development builds.
extern "C" const char* __asan_default_options() {
return "include_if_exists=/system/asan.options:detect_container_overflow=0:abort_on_error=1";
}
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) extern "C" void
__sanitizer_report_error_summary(const char* summary) {
LOG(ERROR) << "Init (error summary): " << summary;
}
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) static void
AsanReportCallback(const char* str) {
LOG(ERROR) << "Init: " << str;
}
#endif
using namespace android::init;
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
return FirstStageMain(argc, argv);
}
android 13 .rc 文件位置
/system/core/rootdir/init.rc
1、里面包含了 ueventd 的啟動(dòng),
## Daemon processes to be run by init.
##
service ueventd /system/bin/ueventd
class core
critical
seclabel u:r:ueventd:s0
shutdown critical
service console /system/bin/sh
class core
console
disabled
user shell
group shell log readproc
seclabel u:r:shell:s0
setenv HOSTNAME console
2、包含了 servermanager 啟動(dòng)
start servicemanager
start hwservicemanager
start vndservicemanager
AndroidRuntime
AndroidRuntime.cpp
start
startVm
startReg //注冊(cè)JNI
反射調(diào)用ZygoteInit.java 的main
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
// Whether this is the primary zygote, meaning the zygote which will fork system server.
bool primary_zygote = false;
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
primary_zygote = true;
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /system does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
const char* artRootDir = getenv("ANDROID_ART_ROOT");
if (artRootDir == NULL) {
LOG_FATAL("No ART directory specified with ANDROID_ART_ROOT environment variable.");
return;
}
const char* i18nRootDir = getenv("ANDROID_I18N_ROOT");
if (i18nRootDir == NULL) {
LOG_FATAL("No runtime directory specified with ANDROID_I18N_ROOT environment variable.");
return;
}
const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");
if (tzdataRootDir == NULL) {
LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable.");
return;
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
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);
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.
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
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 {
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");
}
ZygoteInit.java
main()
preLoad();//預(yù)加載
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginPreload");
beginPreload();
bootTimingsTraceLog.traceEnd(); // BeginPreload
bootTimingsTraceLog.traceBegin("PreloadClasses");
preloadClasses();
bootTimingsTraceLog.traceEnd(); // PreloadClasses
bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
cacheNonBootClasspathClassLoaders();
bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
bootTimingsTraceLog.traceBegin("PreloadResources");
preloadResources();
bootTimingsTraceLog.traceEnd(); // PreloadResources
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
nativePreloadAppProcessHALs();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
maybePreloadGraphicsDriver();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
preloadSharedLibraries();
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
endPreload();
warmUpJcaProviders();
Log.d(TAG, "end preload");
sPreloadComplete = true;
}
/system/bin/app_process64
是通過(guò) zygote fork 出來(lái), 具備vm 和完整 sdk結(jié)構(gòu) , 可執(zhí)行 dex文件;