init启动流程总结分析详解.docx
《init启动流程总结分析详解.docx》由会员分享,可在线阅读,更多相关《init启动流程总结分析详解.docx(22页珍藏版)》请在冰豆网上搜索。
init启动流程总结分析详解
Init启动流程
Android:
4.2.2
Linux内核:
3.1.10
内核空间和应用空间是不能直接通过内存地址级别访问的,所以就需要建立某种通讯机制。
目前Linux有很多通讯机制可以在用户空间和内核空间之间交互,
例如设备驱动文件(位于/dev目录中)、内存文件(/proc、/sys目录等)
这些与内核空间交互的文件都在用户空间,所以在Linux内核装载完,需要首先建立这些文件所在的目录。
而完成这些工作的程序就是本文要介绍的init。
Init是一个命令行程序。
其主要工作之一就是建立这些与内核空间交互的文件所在的目录。
当Linux内核加载完后,要做的第一件事就是调用init程序,也就是说,init是用户空间执行的第一个程序。
在分析init的核心代码之前,还需要初步了解init除了建立一些目录外,还做了如下的工作
1.初始化属性
2.处理配置文件的命令(主要是init.rc文件),包括处理各种Action。
3.性能分析(使用bootchart工具)。
4.无限循环执行command(启动其他的进程)。
尽管init完成的工作不算很多,不过代码还是非常复杂的。
Init程序并不是由一个源代码文件组成的,而是由一组源代码文件的目标文件链接而成的。
这些文件位于如下的目录。
/system/core/init
其中init.c是init的主文件,现在打开该文件,看看其中的内容。
由于init是命令行程序,所以分析init.c首先应从main函数开始,现在好到main函数,代码如下:
intmain(intargc,char**argv)
{
intfd_count=0;
structpollfdufds[4];
char*tmpdev;
char*debuggable;
chartmp[32];
intproperty_set_fd_init=0;
intsignal_fd_init=0;
intkeychord_fd_init=0;
boolis_charger=false;
//启动ueventd
if(!
strcmp(basename(argv[0]),"ueventd"))
returnueventd_main(argc,argv);
//启动watchdogd
if(!
strcmp(basename(argv[0]),"watchdogd"))
returnwatchdogd_main(argc,argv);
/*cleartheumask*/
umask(0);
//下面的代码开始建立各种用户空间的目录,如/dev、/proc、/sys等
//为rootfs创建并挂在启动所需的文件目录
mkdir("/dev",0755);
mkdir("/proc",0755);
mkdir("/sys",0755);
mount("tmpfs","/dev","tmpfs",MS_NOSUID,"mode=0755");
mkdir("/dev/pts",0755);
mkdir("/dev/socket",0755);
mount("devpts","/dev/pts","devpts",0,NULL);
mount("proc","/proc","proc",0,NULL);
mount("sysfs","/sys","sysfs",0,NULL);
/*检测/dev/.booting文件是否可读写和创建*/
close(open("/dev/.booting",O_WRONLY|O_CREAT,0000));
//创建/dev/null节点,需要在后面的程序中看到打印信息的话,需要屏蔽掉这个函数
open_devnull_stdio();
//log初始化
//klog_init()用于初始化log,通过其实现可以看出log被打印到/dev/__kmsg__文件中。
//主要在代码中最后通过fcntl和unlink使得/dev/__kmsg__不可被访问,
//这就保证了只有log程序才可以访问。
klog_init();//在/system/core/libcutils/Klog.c中
//属性服务初始化
property_init();
//从/proc/cpuinfo中读取Hardware名,在后面的mix_hwrng_into_linux_rng_action函数
//中会将hardware的值设置给属性ro.hardware
//get_hardware_name()函数的作用是从/proc/cpuinfo中获取Hardware和Revision的值,//并保存到全局变量hardware和revision中。
get_hardware_name(hardware,&revision);
//导入并设置内核变量,处理内核命令行
process_kernel_cmdline();
//selinux相关,暂不分析
unionselinux_callbackcb;
cb.func_log=klog_write;
selinux_set_callback(SELINUX_CB_LOG,cb);
cb.func_audit=audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT,cb);
selinux_initialize();
/*Thesedirectorieswerenecessarilycreatedbeforeinitialpolicyload
*andthereforeneedtheirsecuritycontextrestoredtothepropervalue.
*Thismusthappenbefore/devispopulatedbyueventd.
*/
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon_recursive("/sys");
is_ffbm=!
strncmp(bootmode,"ffbm",4);
if(!
is_ffbm)
is_charger=!
strcmp(bootmode,"charger");//关机充电相关,暂不做分析
INFO("propertyinit\n");
if(!
is_charger)
property_load_boot_defaults();
INFO("readingconfigfile\n");
//解析/init.rc配置文件的内容
init_parse_config_file("/init.rc");
//执行初始化文件中的动作
/*
∙*解析完init.rc后会得到一系列的action等,下面的代码将执行处于early-init阶段的action。
∙*init将action按照执行时间段的不同分为early-init、init、early-boot、boot。
∙*进行这样的划分是由于有些动作之间具有依赖关系,某些动作只有在其他动作完成后才能执行,所以就有了先后的区别。
∙*具体哪些动作属于哪个阶段是在init.rc中的配置决定的
∙*/
action_for_each_trigger("early-init",action_add_queue_tail);
queue_builtin_action(wait_for_coldboot_done_action,"wait_for_coldboot_done");
queue_builtin_action(mix_hwrng_into_linux_rng_action,
"mix_hwrng_into_linux_rng");
queue_builtin_action(keychord_init_action,"keychord_init");
queue_builtin_action(console_init_action,"console_init");
/*executeallthebootactionstogetusstarted*/
action_for_each_trigger("init",action_add_queue_tail);
//在charger模式下略过mount文件系统的工作
if(!
is_charger){
action_for_each_trigger("early-fs",action_add_queue_tail);
action_for_each_trigger("fs",action_add_queue_tail);
action_for_each_trigger("post-fs",action_add_queue_tail);
action_for_each_trigger("post-fs-data",action_add_queue_tail);
}
queue_builtin_action(property_service_init_action,"property_service_init");
queue_builtin_action(signal_init_action,"signal_init");
queue_builtin_action(check_startup_action,"check_startup");
if(is_charger){
action_for_each_trigger("charger",action_add_queue_tail);
}else{
action_for_each_trigger("early-boot",action_add_queue_tail);
action_for_each_trigger("boot",action_add_queue_tail);
}
/*runallpropertytriggersbasedoncurrentstateoftheproperties*/
queue_builtin_action(queue_property_triggers_action,"queue_property_triggers");
#ifBOOTCHART
queue_builtin_action(bootchart_init_action,"bootchart_init");
#endif
//进入无限循环,建立init的子进程(init是所有进程的父进程)
for(;;){
intnr,i,timeout=-1;
//执行命令(子进程对应的命令)
//检查action_queue列表是否为空。
如果不为空则移除并执行列表头中的action
execute_one_command();
resta