Android系统启动流程
一、Bootloader引导
路径:bootable/bootloader/*
加电后,CPU先执行bootloader引导程序,正常启动系统,加载boot.img到RAM,然后执行,boot.img中包含内核。
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的,不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行。第一个阶段,检测外部的RAM及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
二、Linux Kernel启动
路径:kernel/*
由bootloader加载kernel,kernel经自解压、初始化、载入built-in驱动程序,完成启动。Kernel启动后会创建若干内核线程(kernel thread),之后装入并执行程序/sbin/init/,载入init process,切换至user-space。
三、Android启动
Android从Linux系统启动有4个步骤:
1) init进程启动
2) Native服务启动
3) System Server,Android服务启动
4) Home启动
总体启动框架如下图:
3.1 init进程启动
路径:system/core/init
Init进程是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程,我们可以称它为root进程或者所有进程的父进程。
Init进程一起来就根据init.rc和init.xxx.rc(硬件平台相关)脚本文件建立个几个基本服务:
ServiceManager
Zygote
Vold
......
最后init并不退出,而是担当property service的功能。
服务启动机制:
1) system/core/init/init.cpp文件main函数中parse_config_file(init.rc)读取并解析init.rc文件内容。将service信息放置到system/core/init/init_parser.cpp的service_list中
2) system/core/init/init.cpp文件main函数继续执行restart_servie_if_needed(...) -> service_start(...) -> Execve(...)建立service进程
Init.rc是Android自己规定的初始化脚本(Android Init Language, system/core/init/readme.txt),该脚本包含四个类型声明:
Actions
Commands
Services
Options(对服务的描述,影响init进程如何以及何时启动服务)
具体在system/core/init/init.cpp中,会一步步完成以下工作:
1) 启动准备:该阶段包括创建文件系统的基本目录、打开基本输入、输出设备,初始化日志功能等;
mkdir -> mount -> open_devnull_stdio -> klog_init
2) 解析init.rc文件:该阶段对init.rc脚本文件进行解析,主要对service和action进行解析并放入到对应的service/action_list列表中,其中Service由命令(command)和一系列服务的附加内容(option)选项组成,如:”service vold /system/bin/vold”为一个service,而”socket vold stream 0660 root mount”则为配合该服务使用的option;Action则由一系列的命令组成,如:”on init mkdir /system”为系统初始化时建立系统文件夹的action;
init_parse_config_file -> parse_config -> parse_new_section -> parse_service/parse_action -> parse_line_service/parse_line_action
3) 触发需要执行的action:Action需要在Triggers(触发条件)中调用,本阶段对需要执行的Action进行触发,并根据触发条件将需要执行的Action放入Action队列;
action_for_each_trigger(early-init,init,charger,ffbm,late-init) -> action_add_queue_tail -> action_remove_queue_head -> do_class_start
4) 执行在action队列中的命令:对上一阶段触发的Action及Service进行执行,并在此过程中,派生了Zygote和ServiceManager两个非常重要的进程;
execute_one_command -> action_remove_queue_head -> do_class_start -> service_for_each_class -> service_start_if_not_disable -> service_start
5) 循环处理事件:init进程进入无限循环,处理设备插入/拔出,服务属性状态变化和signal事件等。
while (true) {
Poll -> handle_property_set_fd -> handle_keychord -> handle_signal
}
这里列出默认的init.rc文件主要的事件以及服务:
Action/Service |
描述 |
on early-init |
设置init进程及其子进程的优先级,设置init进程的安全环境 |
on init |
设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点 |
on fs |
挂载mtd分区 |
on post-fs |
改变系统目录的访问权限 |
on post-fs-data |
改变/data目录以及它的子目录的访问权限 |
on boot |
基本网络的初始化,内存管理等等 |
service servicemanager |
启动系统管理器管理所有的本地服务,比如位置、音频、Sharedpreference等等… |
service zygote |
启动zygote作为应用进程 |
在这个阶段可以在设备的屏幕上看到“Android”logo了。
3.2 ServiceManager
ServiceManager属于Native service。在执行init.rc时就会启动,与Zygote一样。在init.rc脚本中ServiceManager的描述:
service servicemanager /system/bin/servicemanager
所以servicemanager从frameworks/native/cmds/servicemanager/service_manager.main(..)开始
int main(int argc, char **argv)
{
struct binder_state *bs;
// 打开/dev/binder设备,并在内存中映射128k的空间
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
// 通知Binder设备,把自己变成context_manger
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
selinux_enabled = is_selinux_enabled();
sehandle = selinux_android_service_context_handle();
selinux_status_open(true);
if (selinux_enabled > 0) {
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
abort();
}
}
union selinux_callback cb;
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
cb.func_log = selinux_log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
// 进入循环,不停的去读Binder设备,看是否有对service的请求,如果有就会调用svcmgr_handler函数回调处理请求
binder_loop(bs, svcmgr_handler);
return 0;
}
在servicemanager中的svcmgr_handler负责处理Android中所有有关service的请求响应
int svcmgr_handler(...,...struct binder_io *reply)
{
......
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
......
case SVC_MGR_ADD_SERVICE:
......
case SVC_MGR_LIST_SERVICES:
......
}
如在SystemServer中注册各种Android中的service时,调用的ServiceManager.addService(“entropy”,new EntropyService);即最终调用该servicemanager中SVC_MGR_ADD_SERVICE,执行do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, txn->sender_pid)接口,由servicemanager负责注册各项服务。注册后,会将该service加入svcList中。svcList中存了各个注册过的service的name和handler。
当接收到获取service的请求时,则会执行SVC_MGR_CHECK_SERVICE,do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);...bio_put_ref(reply, handle); servicemanager会查找该service,如果存在,把返回数据写入reply,返回给客户。
3.3 Zygote
Servicemanager和zygote进程奠定了Android的基础。Zygote这个进程起来才会拉起真正的Android运行空间,初始化建立的service都是Native service,在.rc脚本文件中zygote的描述:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
所以zygote从frameworks/base/cmds/app_main.main(..)开始
建立java runtime
runtime.start("com.android.internal.os.ZygoteInit", args, zygote)
该函数中:
1) 创建Dalvik Java虚拟机,JNI_CreateJavaVM(...)
2) 注册Android Runtime中的JNI接口给虚拟机
3) 呼叫Java类com.android.internal.os.ZygoteInit中的main函数
Frameworks/base/core/java/com/android/internal/os/ZygoteInit.java的main中:
1) registerZygoteSocket(); // 注册listen端口,用来接收请求
2) Preload(); //预加载class、resources用来加快启动速度并初始化核心内库,文件清单在framework.jar中的preloaded-class,framework-res.apk中的res中,
3) startSystemServer(); // 启动system server
4) 进入zygote服务框架
经过以上步骤zygote就建立完成,利用socket通信,接收ActivityManagerService的请求,fork应用程序。
在这个阶段,你可以看到启动动画。
3.4 System Server
1) startSystemServer()中通过Zygote.forkSystemServer(...) fork出独立的进程,名称为 system-server,Android的所有服务循环框架都建立在SystemServer上。
2) handleSystemServerProcess(...)
RuntimeInit.zygoteInit(...)
nativeZygoteInit() //最终呼叫的是AppRuntime.onZygoteInit函数
applicationInit(...) -> invokeStaticMain(...) //呼叫com.android.server.SystemServer类中的main函数
3) com.android.server.SystemServer.main中创建线程注册各种service到servicemanager中
Looper.prepareMainLooper();进入循环
System.loadLibrary("android_servers"); 首先加载android_server共享库,源码位于frameworks/base/service/jni,该库中定义jni_onload函数,Dalvik在加载libandroid_server.so时,会呼叫该函数,该函数将android server注册到java虚拟机中,如HardwareService,AlarmService等;
startBootstrapServices();
startCoreServices();
startOtherServices();
Looper.loop();
核心服务:
启动电源管理器;
创建Activity管理器;
启动电话注册;
启动包管理器;
设置Activity管理服务为系统进程;
启动上下文管理器;
启动系统Context Providers;
启动电池服务;
启动定时管理器;
启动传感服务;
启动窗口管理器;
启动蓝牙服务;
启动挂载服务。
其他服务:
启动状态栏服务;
启动硬件服务;
启动网络状态服务;
启动网络连接服务;
启动通知管理器;
启动设备存储监视服务;
启动定位管理器;
启动搜索服务;
启动剪切板服务;
启动登记服务;
启动壁纸服务;
启动音频服务;
启动耳机监听;
启动AdbSettingsObserver(处理adb命令)。
3.5 Home启动
在SystemServer.startOtherServices()的后半段,启动完所有的Android服务后,进行如下操作:if(xxxService != null) xxxService.systemReady();通知各个服务,系统已经准备就绪。
对于mActivityManagerService.systemReady(new Runnable() {
public void run() {
startSystemUi(context);
wallpaperF.systemRunning();
...
}
}
Home就是在ActivityManagerService.systemReady通知过程中建立的。
public void systemReady(final Runnable goingCallback) {
synchronized(this) {
...
startHomeActivityLocked(mCurrentUserId, "systemReady");
...
mStackSupervisor.resumeTopActivitiesLocked();
...
}
}
startHomeActivityLocked(userId, reason){
...
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);//根据intent的Action和Category信息寻找出适合启动的Activity信息,结果会返回Launcher所在的包名及类名等信息
...
mStackSupervisor.startHomeActivity(intent, aInfo, reason);
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);//新建一个intent,其中mTopAction为Intent.ACTION_MAIN,mTopData的值为null
...
intent.addCategory(Intent.CATEGORY_HOME);
return intent;
}
void startHomeActivity(intent, aInfo, reason) {
...
startActivityLocked(...);
...
}
startActivityLocked(...){
...
//根据传入的Intent及Activity的Info实例化一个ActivityRecord对象,初始化过程中会去获得该Activity的各种信息,一个ActivityRecord对象中包含了该Activity的各种信息,是HistoryStack的入口
ActivityRecord r = new ActivityRecord(...);
...
err = startActivityUncheckedLocked(r,...);
...
}
startActivityUncheckedLocked(r,...){
...
targetStack.startActivityLocked(r,...);
...
}
startActivityLocked(r,...){
...
r.putInHistory();
...
//重新调用该函数,启动处于栈顶的Activity
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
final ActivityRecord next = topRunningActivityLocked(null);
...
mWindowManager.setAppVisibility(next.appToken, true);
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
realStartActivityLocked(r, app, andResume, checkConfig);//该接口实例化一个Launcher Activity对象
...
//该接口会启动Launcher Activity进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true, r);
...
Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs);//根据app指定的uid等信息,启动对应的进程
至此Launcher进程便启动完成,完成了HOME的启动。
Step 7:引导完成
1. 一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。