init启动流程总结分析详解.docx

上传人:b****2 文档编号:2020465 上传时间:2022-10-26 格式:DOCX 页数:22 大小:175.15KB
下载 相关 举报
init启动流程总结分析详解.docx_第1页
第1页 / 共22页
init启动流程总结分析详解.docx_第2页
第2页 / 共22页
init启动流程总结分析详解.docx_第3页
第3页 / 共22页
init启动流程总结分析详解.docx_第4页
第4页 / 共22页
init启动流程总结分析详解.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

init启动流程总结分析详解.docx

《init启动流程总结分析详解.docx》由会员分享,可在线阅读,更多相关《init启动流程总结分析详解.docx(22页珍藏版)》请在冰豆网上搜索。

init启动流程总结分析详解.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1