i.mx6 Android5.1.1 初始化流程之init进程(未完成)

时间:2022-02-21 09:26:31

概述:

 

接在i.mx6 Android5.1.1 初始化流程之框架之后

参考资料:http://blog.csdn.net/mr_raptor/article/category/799879

相关源码:  /system/core/init/

相关配置文件:/system/core/rootdir/

 

从下面全文可以得出:

1).init进程和其相关的文件init.rc、ueventd.rc是在ramdisk.img中

2).修改节点权限:  /ueventd.rc   /ueventd.Freescale.rc

3). 修改相关服务和创建文件:/init.rc  

 

1. mian.c

关于代码中的属性服务,可以查看:i.mx6 Android5.1.1 系统属性   

关于代码中的init.rc,可以查看:      i.mx6 Android5.1.1 初始化流程之init.rc解析

int main(int argc, char **argv)
{
int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
char tmp[32];
int property_set_fd_init = 0;
int signal_fd_init = 0;
int keychord_fd_init = 0;
bool is_charger = false;
char watchdog[PROPERTY_MAX_VALUE];
int ret;

  /*后面两个是初始化ueventd和看门狗,从上一章的ps中可以看出,这两个确实是进程init(PID=1)最初创建的两个进程*/
  /*查看是否有看门狗的属性*/ ret
= property_get("ro.boot.watchdogd", watchdog);
  /*启动ueventd进程*/
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
  
if (!strcmp(basename(argv[0]), "watchdogd")) {
if(ret && !(strcmp(watchdog, "disabled"))) {
return 0;
}
else {
return watchdogd_main(argc, argv); /*在这里启动看门狗*/
}
}

/* clear the umask */
umask(
0);

/* Get the basic filesystem setup we need put
* together in the initramdisk on / and then we'll
* let the rc file figure out the rest.
*/

  /* 创建目录,挂在文件系统,给权限
   * tmpfs :/dev

   * devpts :/dev/pts
   * proc :/proc  
   * sysfs :/sys
   */ 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);

close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));

open_devnull_stdio(); //将标准输入、输出、错误定向到空
klog_init();    
//将log重定向到/proc/kmsg当中
property_init(); //初始化属性服务,关于属性服务,可以查看:i.mx6 Android5.1.1 系统属性

get_hardware_name(hardware,
&revision); //得到硬件信息和版本信息
get_soc_name(soc); //得到soc名字

process_kernel_cmdline();
// 设置基本属性

union selinux_callback cb;
cb.func_log
= log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);

cb.func_audit
= audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);

selinux_initialize();
/* These directories were necessarily created before initial policy load
* and therefore need their security context restored to the proper value.
* This must happen before /dev is populated by ueventd.
*/
restorecon(
"/dev");
restorecon(
"/dev/socket");
restorecon(
"/dev/__properties__");
restorecon_recursive(
"/sys");

is_charger
= !strcmp(bootmode, "charger");

INFO(
"property init\n");
property_load_boot_defaults();
//加载/default.prop文件 进行默认属性配置相关的工作


INFO(
"reading config file\n");
init_parse_config_file(
"/init.rc"); //注意:解析/init.rc,并将所有元素加入链表,关于init.rc,可以查看:i.mx6 Android5.1.1 系统属性 

  /* 首先说明一下,在函数中对于init.rc命令的解析之后,将所有命令分类分别挂在了action_list,service_list,action_queue三个链表当中
   *
serevice_list:用于保存init.rc当中的service配置信息
   * action_list: 用于保存从init.rc当中解析出来的所有action
   * action_queue: 用于保存所有待执行的action
   *
   * 下面的两个函数action_for_each_trigger和queue_builtin_action

   * action_for_each_trigger:将action加入到action_queue当中,表示正准备执行
   * queue_builtin_action: 创建一个action,并将其挂在atcion_queue和action_list当中,
   */
    action_for_each_trigger("early-init", action_add_queue_tail); //接着上面,把链表中为on early-init的元素提取执行。(我们没有)将early-init动作添加到链表action_queue中   

queue_builtin_action(wait_for_coldboot_done_action,
"wait_for_coldboot_done"); //创建wait_for_coldboot_done动作并添加到链表action_queue和action_list中,在这里注意action_list用于保存从init.rc中解析出来的所有Action,而action_queue却是用于保存待执行的Action,action_queue是一个待执行队列。

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");

/* execute all the boot actions to get us started */
action_for_each_trigger(
"init", action_add_queue_tail);//执行Init.rc中的on init(这个我们就有了),后面分析

/* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
* wasn't ready immediately after wait_for_coldboot_done
*/
queue_builtin_action(mix_hwrng_into_linux_rng_action,
"mix_hwrng_into_linux_rng");
queue_builtin_action(property_service_init_action,
"property_service_init");
queue_builtin_action(signal_init_action,
"signal_init");

/* Don't mount filesystems or start core system services if in charger mode. */
if (is_charger) {
action_for_each_trigger(
"charger", action_add_queue_tail); //执行这个,不执行下面的
} else {
action_for_each_trigger(
"late-init", action_add_queue_tail);
}

/* run all property triggers based on current state of the properties */
queue_builtin_action(queue_property_triggers_action,
"queue_property_triggers");


#if BOOTCHART
queue_builtin_action(bootchart_init_action,
"bootchart_init");
#endif
  
for(;;) {
int nr, i, timeout = -1;

execute_one_command();
//按序执行action_queue里的action
restart_processes(); //重启一些关键进程,也就是守护进程
//添加,只执行一次
if (!property_set_fd_init && get_property_set_fd() > 0) {
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;

#if BOOTCHART
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();
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
}

return 0;
}

 

小结:

1。启动ueventd和watchdogd进程

2。将标准输入,输出,错误定向到null

3.重定向log

4.初始化属性的区域

5.添加各种属性

6.解析init.rc

7.将init.rc中解析出来的行为进行分类保存,并再添加一些默认行为

8.进入循环守护

  1). 执行action_queue中的action

  2). 守护一些关键进程

  3). 建立属性、信号、组合按键的监听。当有行为发生时,对其进行相应处理,没有则停滞在这里 

 

 

从上诉程序可以分析出action的执行顺序为:

early-init                   ------------------>>init.rc
wait_for_coldboot_done
mix_hwrng_into_linux_rng
keychord_init
console_init
init         ------------------>>init.rc
mix_hwrng_into_linux_rng
property_service_init
signal_init
charger或者late-init  ------------------>>init.rc
queue_property_triggers

 

2. ueventd_main

int ueventd_main(int argc, char **argv)
{
struct pollfd ufd;
int nr;
char tmp[32];

/*
* init sets the umask to 077 for forked processes. We need to
* create files with exact permissions, without modification by
* the umask.
*/
umask(
000);

/* Prevent fire-and-forget children from becoming zombies.
* If we should need to wait() for some children in the future
* (as opposed to none right now), double-forking here instead
* of ignoring SIGCHLD may be the better solution.
*/
signal(SIGCHLD, SIG_IGN);

open_devnull_stdio();
klog_init();
#if LOG_UEVENTS
/* Ensure we're at a logging level that will show the events */
if (klog_get_level() < KLOG_INFO_LEVEL) {
klog_set_level(KLOG_INFO_LEVEL);
}
#endif

union selinux_callback cb;
cb.func_log
= log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);

INFO(
"starting ueventd\n");

/* Respect hardware passed in through the kernel cmd line. Here we will look
* for androidboot.hardware param in kernel cmdline, and save its value in
* hardware[].
*/
import_kernel_cmdline(
0, import_kernel_nv);

get_hardware_name(hardware,
&revision);
//解析ueventd.rc和ueventd.fressale.rc
ueventd_parse_config_file("/ueventd.rc");

snprintf(tmp,
sizeof(tmp), "/ueventd.%s.rc", hardware);
ueventd_parse_config_file(tmp);
//设备初始化
device_init();

ufd.events
= POLLIN;
ufd.fd
= get_device_fd();

while(1) {
ufd.revents
= 0;
nr
= poll(&ufd, 1, -1); //循环等待
if (nr <= 0)
continue;
if (ufd.revents & POLLIN)
handle_device_fd();
//讲接收过来的信息进行处理
}
}

 

 

 

 

往下查看 i.mx6 Android5.1.1 初始化流程之init.rc解析