Android系统分层
1.Linux 内核 。例如,Android Runtime (ART) 依靠 Linux 内核来执行底层功能。例如线程和低层内存管理。
2.硬件抽象层 (HAL) 提供标准界面,向更高级别的 Java API 框架显示设备硬件功能。HAL 包含多个 库模块,其中每个模块都为特定类型的硬件组件实现一个界面,例如相机或蓝牙模块。
3.Android Runtime
对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART 编写为通过执行 DEX 文件在低内存设备上运行 多个虚拟机。
ART 的部分主要功能包括: 预先 (AOT) 和即时 (JIT) 编译 优化的垃圾回收 (GC) 在 Android 9(API 级别 28)及更高版本的系统中,支持将应用软件包中的 Dalvik Executable 格 式 (DEX) 文件转换为更紧凑的机器代码。 更好的调试支持,包括专用采样分析器、详细的诊断异常和崩溃报告,并且能够设置观察点以监控 特定字段 在 Android 版本 5.0(API 级别 21)之前,Dalvik 是 Android Runtime。如果您的应用在 ART 上 运行效果很好,那么它应该也可在 Dalvik 上运行,但反过来不一定。 Android 还包含一套核心运行时库,可提供 Java API 框架所使用的 Java 编程语言中的大部分功能,包括 一些 Java 8 语言功能。
4.原生 C/C++ 库 许多核心 Android 系统组件和服务(例如 ART 和 HAL)构建自原生代码,需要以 C 和 C++ 编写的 原生库。
5.Java API 框架 您可通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。
丰富、可扩展的视图系统,可用以构建应用的 UI,包括列表、网格、文本框、按钮甚至可嵌入的网 络浏览器
资源管理器,用于访问非代码资源,例如本地化的字符串、图形和布局文件
通知管理器,可让所有应用在状态栏中显示自定义提醒
Activity 管理器,用于管理应用的生命周期,提供常见的导航返回栈
内容提供程序,可让应用访问其他应用(例如“联系人”应用)中的数据或者共享其自己的数据
6.系统应用 Android 随附一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。
Android系统启动流程
第一步: 启动电源以及系统启动BootROM
当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载
引导程序
到RAM,然后执行。
第二步: 引导程序BootLoader
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运 营商加锁和限制的地方。 引导程序分两个阶段执行。 第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序; 第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。 Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。传统的加载器包含两个文件, 需要在这里说明: init.s初始化堆栈,清零BBS段,调用main.c的_main()函数; main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签
第三步:内核Kernel
Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表, 加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第 一个进程
第四步:init进程
init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进 程,并调用init.cpp中的main()方法执行init进程的职责。
第五步:启动Lancher App
init进程分析
init进程是Android系统中及其重要的第一个进程,接下来我们来看下init进程注意做了些什么
- 创建和挂载启动所需要的文件目录
- 初始化和启动属性服务
- 解析init.rc配置文件并启动Zygote进程
// \system\core\init\init.cpp
int main(int argc, char** argv) {
//当argv[0]的内容为ueventd时,也就执行ueventd_main,主要是负责设备节点的创建、权限设定等一些列工作
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
//watchdogd俗称看门狗,用于系统出问题时重启系统
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
//...
if (REBOOT_BOOTLOADER_ON_PANIC) {
//初始化重启系统的处理信号,内部通过sigaction 注册信号,当监听到该信号时重启系统
InstallRebootSignalHandlers();
}
//...
LoadBootScripts(am, sm);//解析xxx.rc
//...
}
init.rc解析
init.rc是一个非常重要的配置文件,它是由Android初始化语言(Android Init Language)编写的脚 本,它主要包含五种类型语句:Action(Action中包含了一系列的Command)、Commands(init语言 中的命令)、Services(由init进程启动的服务)、Options(对服务进行配置的选项)和Import(引入 其他配置文件)。init.rc的配置代码如下所示。
// \system\core\init\init.cpp
static void LoadBootScripts(ActionManager& action_manager, ServiceList&
service_list) {
Parser parser = CreateParser(action_manager, service_list);//创建解析器
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
parser.ParseConfig("/init.rc");
if (!parser.ParseConfig("/system/etc/init")) {
late_import_paths.emplace_back("/system/etc/init");
}
if (!parser.ParseConfig("/product/etc/init")) {
late_import_paths.emplace_back("/product/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) {
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
} else {
parser.ParseConfig(bootscript);//开始解析
}
}
//上面一直在解析init.rc文件。解析完成后,接下来就是启动Main类型Service。
//# \system\core\rootdir\init.rc L680
//on nonencrypted
//class_start main //class_start是一个命令,通过do_class_start函数处理
//class_start late_start
//经过一系列调用,回走到
// \system\core\init\service.cpp Start() L785
Result<Success> Service::Start() {
//如果service已经运行,则不启动
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
// It is not an error to try to start a service that is already running.
return Success();
}
//...
//判断需要启动的service的对应的执行文件是否存在,不存在则不启动service
//...
//如果子进程没有启动,则调用fork函数创建子进程
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork();
}
if (pid == 0) {//当期代码逻辑在子进程中运行
umask(077);
//调用execv函数,启动sevice子进程,最终会调用app_mian.cpp的,main方法
if (!ExpandArgsAndExecv(args_)) {
PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}
_exit(127);
}
return Success()
}
Zygote概叙
Zygote中文翻译为“受精卵”,正如其名,它主要用于孵化子进程。在Android系统中有以下两种程序:1. java应用程序,主要基于ART虚拟机,所有的应用程序apk都属于这类;2. native程序,也就是利用C或C++语 言开发的程序,如bootanimation。
所有的Java应用程序进程及系统服务SystemServer进程都由Zygote 进程通过Linux的fork()函数孵化出来的,这也就是为什么把它称为Zygote的原因,因为他就像一个受精 卵,孵化出无数子进程,而native程序则由Init程序创建启动。Zygote进程最初的名字不是“zygote”而是 “app_process”,这个名字是在Android.mk文件中定义的
Zgyote是Android中的第一个art虚拟机,他通过socket的方式与其他进程进行通信。这里的“其他进程” 其实主要是系统进程——SystemServer
Zygote是一个C/S模型,Zygote进程作为服务端,它主要负责创建Java虚拟机,加载系统资源,启动SystemServer进程,以及在后续运行过程中启动普通的应用程序,其他进程作为客户端向它发 出“孵化”请求,而Zygote接收到这个请求后就“孵化”出一个新的进程。比如,当点击Launcher里的应用程序图标去启动一个新的应用程序进程时,这个请求会到达框架层的核心服务 ActivityManagerService中,当AMS收到这个请求后,它通过调用Process类发出一个“孵化”子进 程的Socket请求,而Zygote监听到这个请求后就立刻fork一个新的进程出来
Zygote启动过程
在app_main.cpp的main函数中,主要做的事情就是参数解析. 这个函数有两种启动模式:
- 一种是zygote模式,也就是初始化zygote进程,传递的参数有–start-system-server –socketname=zygote,前者表示启动SystemServer,后者指定socket的名称
- 一种是application模式,也就是启动普通应用程序,传递的参数有class名字以及class带的参数 两者最终都是调用AppRuntime对象的start函数,加载ZygoteInit或RuntimeInit两个Java类,并将之前 整理的参数传入进去
// \frameworks\base\cmds\app_process\app_main.cpp main() L280
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
}
// L349
if (zygote) {
//这些Java的应用都是通过 AppRuntime.start(className)开始的
//其实AppRuntime是AndroidRuntime的子类,它主要实现了几个回调函数,而start()方法是实现在AndroidRuntime这个方法类里
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
}
app_process 里面定义了三种应用程序类型:
- Zygote: com.android.internal.os.ZygoteInit
- System Server, 不单独启动,而是由Zygote启动
- 其他指定类名的Java 程序
AndroidRuntime::start()流程
// \frameworks\base\core\jni\androidRuntime.cpp start() L1091
void AndroidRuntime::start(const char* className, const Vector<String8>&
options, bool zygote){
//...
JNIEnv* env;
//JNI_CreateJavaVM L1015
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
// ...
}
Java虚拟机的启动大致做了以下一些事情:
- 从property读取一系列启动参数。
- 创建和初始化结构体全局对象(每个进程)gDVM,及对应与JavaVM和JNIEnv的内部结构体 JavaVMExt, JNIEnvExt.
- 初始化java虚拟机,并创建虚拟机线程
- 注册系统的JNI,Java程序通过这些JNI接口来访问底层的资源。
- 为Zygote的启动做最后的准备,包括设置SID/UID, 以及mount 文件系统
- 返回JavaVM 给Native代码,这样它就可以向上访问Java的接口
// \frameworks\base\core\jni\androidRuntime.cpp startVm() L596
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote){
//...
// L1015
//startVM的前半部分是在处理虚拟机的启动参数,处理完配置参数后,会调用libart.so提供的一个接口:JNI_CreateJavaVM函数
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
//...
}
// \art\runtime\java_vm_ext.cc JNI_CreateJavaVM() L1139
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void*
vm_args) {
ScopedTrace trace(__FUNCTION__);
const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
if (JavaVMExt::IsBadJniVersion(args->version)) {
LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args-
>version;
return JNI_EVERSION;
}
RuntimeOptions options;
for (int i = 0; i < args->nOptions; ++i) {
JavaVMOption* option = &args->options[i];
options.push_back(std::make_pair(std::string(option->optionString),
option->extraInfo));
}
bool ignore_unrecognized = args->ignoreUnrecognized;
//通过Runtime的create方法创建单例的Runtime对象
if (!Runtime::Create(options, ignore_unrecognized)) {
return JNI_ERR;
}
// Initialize native loader. This step makes sure we have
// everything set up before we start using JNI.
android::InitializeNativeLoader();
Runtime* runtime = Runtime::Current();
bool started = runtime->Start();//Start()
if (!started) {
delete Thread::Current()->GetJniEnv();
delete runtime->GetJavaVM();
LOG(WARNING) << "CreateJavaVM failed";
return JNI_ERR;
}
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
}
//首先通过Runtime的create方法创建单例的Runtime对象,runtime负责提供art虚拟机的运行时环境,然后调用其init方法来初始化虚拟机
// \art\runtime\runtime.cc Init() L1109
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
//...
// L1255 创建堆管理对象。
heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
runtime_options.GetOrDefault(Opt::HeapMinFree),
runtime_options.GetOrDefault(Opt::HeapMaxFree),
runtime_options.GetOrDefault(Opt::HeapTargetUtilization),
foreground_heap_growth_multiplier,
runtime_options.GetOrDefault(Opt::MemoryMaximumSize),
runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),
runtime_options.GetOrDefault(Opt::Image),
runtime_options.GetOrDefault(Opt::ImageInstructionSet),
// Override the collector type to CC if the read
barrier config.
kUseReadBarrier ? gc::kCollectorTypeCC :
xgc_option.collector_type_,
kUseReadBarrier ?
BackgroundGcOption(gc::kCollectorTypeCCBackground)
:
runtime_options.GetOrDefault(Opt::BackgroundGc),
runtime_options.GetOrDefault(Opt::LargeObjectSpace),
runtime_options.GetOrDefault(Opt::LargeObjectThreshold),
runtime_options.GetOrDefault(Opt::ParallelGCThreads),
runtime_options.GetOrDefault(Opt::ConcGCThreads),
runtime_options.Exists(Opt::LowMemoryMode),
runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
runtime_options.Exists(Opt::IgnoreMaxFootprint),
runtime_options.GetOrDefault(Opt::UseTLAB),
xgc_option.verify_pre_gc_heap_,
xgc_option.verify_pre_sweeping_heap_,
xgc_option.verify_post_gc_heap_,
xgc_option.verify_pre_gc_rosalloc_,
xgc_option.verify_pre_sweeping_rosalloc_,
xgc_option.verify_post_gc_rosalloc_,
xgc_option.gcstress_,
xgc_option.measure_,
runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
//...
// L1408创建java虚拟机对象
std::string error_msg;
java_vm_ = JavaVMExt::Create(this, runtime_options, &error_msg);
if (java_vm_.get() == nullptr) {
LOG(ERROR) << "Could not initialize JavaVMExt: " << error_msg;
return false;
}
// Add the JniEnv handler.
// TODO Refactor this stuff.
java_vm_->AddEnvironmentHook(JNIEnvExt::GetEnvHandler);
Thread::Startup();
// ClassLinker needs an attached thread, but we can't fully attach athread without creating
// objects. We can't supply a thread group yet; it will be fixed later.Since we are the main
// thread, we do not get a java peer.
// L1424 连接主线程
Thread* self = Thread::Attach("main", false, nullptr, false);
CHECK_EQ(self->GetThreadId(), ThreadList::kMainThreadId);
CHECK(self != nullptr);
//...
// L1437 创建类连接器
if (UNLIKELY(IsAotCompiler())) {
class_linker_ = new AotClassLinker(intern_table_);
} else {
class_linker_ = new ClassLinker(intern_table_);
}
if (GetHeap()->HasBootImageSpace()) {
//初始化类连接器
bool result = class_linker_->InitFromBootImage(&error_msg);
if (!result) {
LOG(ERROR) << "Could not initialize from image: " << error_msg;
return false;
}
//...
}
}
}
除了系统的JNI接口(”javacore”, “nativehelper”), android framework 还有大量的Native实现, Android将所有这些接口一次性的通过start_reg()来完成
// \frameworks\base\core\jni\androidRuntime.cpp startReg() L1511
int AndroidRuntime::startReg(JNIEnv* env){
}
ZygoteInit.main()流程
调用完这个函数后,会根据不同情况调用ZygoteInit或者RuntimeInit的main函数
RuntimeInit的 main 函数主要做了。。。主要分析ZygoteInit的main函数
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java main()
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer(); //新建Zygote服务器端
//...
final Runnable caller;
try {
//...
boolean startSystemServer = false;
String socketName = "zygote";//Dalvik VM进程系统
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
//还记得app_main.cpp中传的start-system-server参数吗,在这里总有用到了
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = 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 {
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
zygoteServer.registerServerSocketFromEnv(socketName);//注册Socket
// In some configurations, we avoid preloading resources and
classes eagerly.
fork.
if (!enableLazyPreload) {
// 在有些情况下我们需要在第一个fork之前进行预加载资源
preload(bootTimingsTraceLog);
} else {
Zygote.resetNicePriority();
}
// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
//主动进行一次资源GC
gcAndFinalize();
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale
tracing tags from
// Zygote.
Trace.setTracingEnabled(false, 0);
Zygote.nativeSecurityInit();
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
//fork SystemServer的代码
Runnable r = forkSystemServer(abiList, socketName,
zygoteServer);
{@code r != null} in the
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.
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();
}
}
}
preload
preload() 的作用就是提前将需要的资源加载到VM中,比如class、resource等
preloadClassess 将framework.jar里的preloaded-classes 定义的所有class load到内存里, preloaded-classes 编译Android后可以在framework/base下找到。而preloadResources 将系统的 Resource(不是在用户apk里定义的resource)load到内存。资源preload到Zygoted的进程地址空间, 所有fork的子进程将共享这份空间而无需重新load, 这大大减少了应用程序的启动时间,但反过来增加了 系统的启动时间。通过对preload 类和资源数目进行调整可以加快系统启动。Preload也是Android启动 最耗时的部分之一
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java preload() L123
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
beginIcuCachePinning();
bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
bootTimingsTraceLog.traceBegin("PreloadClasses");
//加载指定的类到内存并且初始化,使用的Class.forName(class, true, null);方式
preloadClasses();
bootTimingsTraceLog.traceEnd(); // PreloadClasses
bootTimingsTraceLog.traceBegin("PreloadResources");
//加载Android通用的资源,比如drawable、color...
preloadResources();
bootTimingsTraceLog.traceEnd(); // PreloadResources
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
nativePreloadAppProcessHALs();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
//加载OpenGL...
preloadOpenGL();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
//加载共用的Library
preloadSharedLibraries();
//加载Text资源,字体等
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in
the zygote process,
// for memory sharing purposes.
// 为了内存共享,WebViewFactory进行任何初始化都要在Zygote进程中
WebViewFactory.prepareWebViewInZygote();
endIcuCachePinning();
warmUpJcaProviders();
Log.d(TAG, "end preload");
sPreloadComplete = true;
}
gcAndFinalize
gc()调用只是通知VM进行垃圾回收,是否回收,什么时候回收全由VM内部算法决定。GC的回收有一个 复杂的状态机控制,通过多次调用,可以使得尽可能多的资源得到回收。gc()必须在fork之前完成(接下 来的StartSystemServer就会有fork操作),这样将来被复制出来的子进程才能有尽可能少的垃圾内存没 有释放
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java gcAndFinalize() L439
static void gcAndFinalize() {
final VMRuntime runtime = VMRuntime.getRuntime();
/* runFinalizationSync() lets finalizers be called in Zygote,
* which doesn't have a HeapWorker thread.
*/
System.gc();
runtime.runFinalizationSync();
System.gc();
}
forkSystemServer
// \frameworks\base\core\java\com\android\internal\os\ZygotInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
//...
//启动SystemServer的命令行,部分参数写死
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--
setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1
024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);//会设
置InvokeWith参数,这个参数在接下来的初始化逻辑中会有调用
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
/* 创建 system server 进程 */
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.runtimeFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {//如果是第一次创建的话pid==0
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
//...
}
//ZygoteInit.forkSystemServer() 方法fork 出一个新的进程,这个进程就是SystemServer进程。fork出来的子进程在handleSystemServerProcess 里开始初始化工作,主要工作分为:
//1. prepareSystemServerProfile()方法中将SYSTEMSERVERCLASSPATH中的AppInfo加载到VM中。
//2. 判断fork args中是否有invokWith参数,如果有则进行WrapperInit.execApplication(不进行深入讲解了)。如果没有则调用ZygoteInit.zygoteInit
// \frameworks\base\core\java\com\android\internal\os\ZygoteInit.java handleSystemServerProcess() L453
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments
parsedArgs) {
//...
if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)){
try {
//将SYSTEMSERVERCLASSPATH中的AppInfo加载到VM中
prepareSystemServerProfile(systemServerClasspath);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile",e);
}
}
if (parsedArgs.invokeWith != null) {
//...
//判断fork args中是否有invokWith参数,如果有则进行 WrapperInit.execApplication
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
//...
//调用zygoteInit
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
//调用zygoteInit后经过一系列调用,会调用到RuntimeInit.applicationInit()方法
// \frameworks\base\core\java\com\android\internal\os\RuntimeInit.java applicationInit() L345
protected static Runnable applicationInit(int targetSdkVersion, String[]
argv,
ClassLoader classLoader) {
...
// Remaining arguments are passed to the start class's static main
//findStaticMain来运行args的startClass的main方法
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
// \frameworks\base\core\java\com\android\internal\os\RuntimeInit.java findStaticMain() L287
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
return new MethodAndArgsCaller(m, argv);
}
// \frameworks\base\core\java\com\android\internal\os\RuntimeInit.java MethodAndArgsCaller L479
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
System Server 启动流程
System Server 是Zygote fork 的第一个Java 进程, 这个进程非常重要,因为他们有很多的系统线程, 提供所有核心的系统服务
看到大名鼎鼎的WindowManager, ActivityManager了吗?对了,它们都是运行在system_server的进程 里。还有很多“Binder-x”的线程,它们是各个Service为了响应应用程序远程调用请求而创建的。除此之 外,还有很多内部的线程,比如 ”UI thread”, “InputReader”, “InputDispatch” 等等,
现在我们只关心System Server是如何创建起来的。 SystemServer的main() 函数。
//SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
//...
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
//初始化系统Context
createSystemContext();
//初始化SystemServiceManager,用来管理启动service,SystemServiceManager中封装了启动Service的startService方法
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.启动系统必要的Service,启动服务的流程又分成三步走:
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
//...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
记下来我分成4部分详细分析SystemServer run方法的初始化流程:
初始化必要的SystemServer环境参数,比如系统时间、默认时区、语言、load一些Library等等,
初始化Looper,我们在主线程中使用到的looper就是在SystemServer中进行初始化的
初始化Context,只有初始化一个Context才能进行启动Service等操作,这里看一下源码:
//SystemServer.java
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
//看到没有ActivityThread就是这个时候生成的 继续看ActivityThread中如何生成Context:
//ActivityThread.java
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
// Start services.
启动BootstrapServices,就是系统必须需要的服务,这些服务直接耦合性很高,所以干脆就放在一个方 法里面一起启动,比如PowerManagerService、RecoverySystemService、DisplayManagerService、 ActivityManagerService等等
启动以基本的核心Service,很简单,只有三个BatteryService、 UsageStatsService、WebViewUpdateService
启动其它需要用到的Service,比如 NetworkScoreService、AlarmManagerServic
补充
fork函数
-
参数:不需要参数
-
需要的头文件 < sys/types.h > 和 < unistd.h >
-
返回值分两种情况:
返回0表示成功创建子进程,并且接下来进入子进程执行流程;
返回PID(>0),成功创建子进程,并且继续执行父进程流程代码
返回非正数(<0),创建子进程失败,失败原因主要有: 进程数超过系统所能创建的上限,errno会被设置为EAGAIN系统内存不足,errno会被设置为 ENOMEM 43 } 1 pid_t fork(void)
使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控 制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信 息)。因此,使用 fork() 函数的代价是很大的
子进程与父进程的区别
- 除了文件锁以外,其他的锁都会被继承 2. 各自的进程ID和父进程ID不同 3. 子进程的未决告警被清除; 4. 子进程的未决信号集设置为空集。
写时拷贝 (copy- on-write)
Linux 的 fork() 使用是通过写时拷贝 (copy- on-write) 实现。写时拷贝是一种可以推迟甚至避免拷贝 数据的技术。内核此时并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间。只用在需 要写入的时候才会复制地址空间,从而使各个进行拥有各自的地址空间。也就是说,资源的复制是在需 要写入的时候才会进行,在此之前,只有以只读方式共享