安卓启动过程
1.当从关机状态开始正常启动时,第一步会执行bootloader,它是从地址0x00开始执行的一段程序,他负责初始化软件运行是所需的最小硬件环境,最后将内核加载进内存中
2.内存加载进内存后,将首先进入内核引导阶段,在引导阶段的最后将会调用start_kernel函数进入内核启动状态,start_kernel函数在最后将会启动用户空间的init程序
3.init:
1)init进程是一个有内核启动的用户级进程,是android系统的第一个进程,进程号为1,是所有进程的父进程
2)init的相关代码在System\system\core\init\init.c下
3)解析init.c的main函数重要部分
…
open_devnull_stdio();//重定向标准输出,输入和出错到null
klog_init();//设置init的日志输出设备为kmeg
property_init();//初始化属性系统所需空间
get_hardware_name(hardware,&revision);//获取硬件信息
process_kernel_cmdline();//处理内核命令行
#ifdefHAVE_SELINUX//安全相关的一些措施
INFO("loadingselinux policy\n");
selinux_load_policy();
#endif
is_charger= !strcmp(bootmode, "charger");//是否在充电模式下
INFO("propertyinit\n");
if(!is_charger)//不在充电模式下,调用函数设置默认属性
property_load_boot_defaults();
INFO("readingconfig file\n");
init_parse_config_file("/init.rc");//!!!很重要的一部分,解析init.rc文件
…
4)经过上面的初始化后和触发action后开始进入无限循环状态,执行command,处理事件
5)bootchart是一个性能统计工具,用于搜集系统和硬件信息,并写入磁盘,以便其他程序使用
6)init.c的main函数的具体功能可以分为4个部分:
初始化文件系统和日志系统,为之后的执行阶段做准备;
解析init.rc和init.<hardware>.rc初始化文件;
触发需要执行的Action和Service;
Init用一个无限循环开始监听事件
4.init.rc文件
1)init.rc的文件格式是有android初始化语言定义,有六个基本概念(Section,Action,Service,Trigger,Command,Option),两个基本关键字(on,service)和多个指令关键字
2)init.rc就是有不同的Section组成的
5.init解析完init.rc后,生成了存放Service和Action的链表,接着执行action_for_each_trigger和queue_builtin_action函数触发Action,接着再使用execute_one_command函数执行action,execute_one_command函数做了两部分工作:取命令和执行命令的func函数。这里的func便是command结构体中的成员函数func,函数代码为:
cmd->func= kw_func(kw);
接下来定位kw_func:
#definekw_func(kw) (keyword_info[kw].func)
这是一个宏定义,需要找到key_word_info的定义。他在init_parser.c中,代码主要定义了所有的Command对应的执行函数,执行Command就是执行这些函数,接着在init.rc文件中,每个aciton对应的Command都能在key_word_info中找到对应,在找到的对应函数中会找到service_start函数,使用service_start函数启动Service(状态不为SVC_DISABLED的Service启动)。init是把service当作一个进程,用command启动,这样所有的service便是init的子进程了,这些由init启动的service为守护进程服务(如ueventd,servicemanager,vold,zygote...),两个最重要的守护进程是zygote和servicemanager,前者是android启动的第一个Dalvik虚拟机,他负责启动java世界的进程,后者是binder通信的基础(注:zygote并不是有init直接启动的,而是app_process将最重要的工作交给了AppRuntime类的start方法去完成,在start方法中调用ZygoteInit类的main方法启动zygote)。
6.init中除了解析init.rc中配置的action和service外,还处理了一些内置的action,这写工作由queue_builtin_action函数完成,进行属性服务的相关操作,定位init.c中的main函数到属性服务相关代码:
property_init();
...
INFO("propertyinit\n");
if(!is_charger)
property_load_boot_defaults();
…
//触发属性服务相关的action
queue_builtin_action(property_service_init_action,"property_service_init");
…
queue_builtin_action(queue_property_triggers_action,"queue_property_triggers");
7.init循环监听处理事件,init触发所有action后,就开始进入无限循环,定位代码:
for(;;){
intnr, i, timeout = -1;
execute_one_command();//启动action和service
restart_processes();//重启action和service
if(!property_set_fd_init && get_property_set_fd() > 0){//分别调用3个函数监听3个fd
ufds[fd_count].fd= get_property_set_fd();
ufds[fd_count].events= POLLIN;
ufds[fd_count].revents= 0;
fd_count++;
property_set_fd_init= 1;
}
if(!signal_fd_init && get_signal_fd() > 0) {
ufds[fd_count].fd= get_signal_fd();
ufds[fd_count].events= POLLIN;
ufds[fd_count].revents= 0;
fd_count++;
signal_fd_init= 1;
}
if(!keychord_fd_init && get_keychord_fd() > 0) {
ufds[fd_count].fd= get_keychord_fd();
ufds[fd_count].events= POLLIN;
ufds[fd_count].revents= 0;
fd_count++;
keychord_fd_init= 1;
}
if(process_needs_restart) {
timeout= (process_needs_restart - gettime()) * 1000;
if(timeout < 0)
timeout= 0;
}
if(!action_queue_empty() || cur_action)
timeout= 0;
#ifBOOTCHART
if(bootchart_count > 0) {
if(timeout < 0 || timeout > BOOTCHART_POLLING_MS)
timeout= BOOTCHART_POLLING_MS;
if(bootchart_step() < 0 || --bootchart_count == 0) {
bootchart_finish();
bootchart_count= 0;
}
}
#endif
nr= poll(ufds, fd_count, timeout);
if(nr <= 0)
continue;
for(i = 0; i < fd_count; i++) {
if(ufds[i].revents == POLLIN) {
if(ufds[i].fd == get_property_set_fd())
handle_property_set_fd();
elseif (ufds[i].fd == get_keychord_fd())
handle_keychord();
elseif (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
}
8.init启动的守护进程中有两个很重要的进程,分别是zygote和servicemanager,zygote是android世界的第一个dalvik虚拟机,所有其他的dalvik虚拟机进程都是通过zygotefork出来的。这有一点很重要,android应用程序是由java语言编写的,运行于各自独立的dalvik中,如果每个应用程序在启动之时都要单独运行和初始化一个虚拟机,会大大降低系统性能,因此android首先创建一个zygote虚拟机,然后通过他复制出其他的虚拟机进程,共享资源,大大提升程序启动和运行速度
9.接着zygote定义和注册了一个Socket,用于接受ActivityManagerService启动应用程序的请求,这个socket的fd由zygote启动是传入,利用Socket通讯,接收ActivityManangerService的请求,Fork应用程序。注册完socket,便进行class资源和resourse资源的预加载
10.zygote通过fork系统调用创建system_server进程,系统在预加载了共享资源后,便开始启动system_server进程,android中所有系统服务都由该进程启动,它的异常退出将导致zygote异常退出,定位代码(ZygoteInit.java文件中):
privatestatic boolean startSystemServer()
throwsMethodAndArgsCaller, RuntimeException {
/*Hardcoded command line to start the system server */
Stringargs[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",