i.mx6 Android5.1.1 初始化流程之init进程(未完成)
概述:
接在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 = ;
struct pollfd ufds[];
char *tmpdev;
char* debuggable;
char tmp[];
int property_set_fd_init = ;
int signal_fd_init = ;
int keychord_fd_init = ;
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[]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[]), "watchdogd")) {
if(ret && !(strcmp(watchdog, "disabled"))) {
return ;
} else {
return watchdogd_main(argc, argv); /*在这里启动看门狗*/
}
} /* clear the umask */
umask(); /* 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", );
mkdir("/proc", );
mkdir("/sys", ); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", );
mkdir("/dev/socket", );
mount("devpts", "/dev/pts", "devpts", , NULL);
mount("proc", "/proc", "proc", , NULL);
mount("sysfs", "/sys", "sysfs", , NULL); close(open("/dev/.booting", O_WRONLY | O_CREAT, )); 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 = -; execute_one_command(); //按序执行action_queue里的action
restart_processes(); //重启一些关键进程,也就是守护进程
//添加,只执行一次
if (!property_set_fd_init && get_property_set_fd() > ) {
ufds[fd_count].fd = get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = ;
fd_count++;
property_set_fd_init = ;
}
/*同上*/
if (!signal_fd_init && get_signal_fd() > ) {
ufds[fd_count].fd = get_signal_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = ;
fd_count++;
signal_fd_init = ;
}
/*同上*/
if (!keychord_fd_init && get_keychord_fd() > ) {
ufds[fd_count].fd = get_keychord_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = ;
fd_count++;
keychord_fd_init = ;
}
//计算超时时间
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * ;
if (timeout < )
timeout = ;
} if (!action_queue_empty() || cur_action)
timeout = ; #if BOOTCHART
if (bootchart_count > ) {
if (timeout < || timeout > BOOTCHART_POLLING_MS)
timeout = BOOTCHART_POLLING_MS;
if (bootchart_step() < || --bootchart_count == ) {
bootchart_finish();
bootchart_count = ;
}
}
#endif
//监控句柄池中的事件,如果都没有变化,程序就停在这里了
nr = poll(ufds, fd_count, timeout);
if (nr <= )
continue;
//对于监听到的事件进行处理
for (i = ; 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 ;
}
小结:
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[]; /*
* init sets the umask to 077 for forked processes. We need to
* create files with exact permissions, without modification by
* the umask.
*/
umask(); /* 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(, 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() {
ufd.revents = ;
nr = poll(&ufd, , -); //循环等待
if (nr <= )
continue;
if (ufd.revents & POLLIN)
handle_device_fd(); //讲接收过来的信息进行处理
}
}
往下查看 i.mx6 Android5.1.1 初始化流程之init.rc解析
i.mx6 Android5.1.1 初始化流程之init进程(未完成)的更多相关文章
- i.mx6 Android5.1.1 初始化流程之init.rc解析(未完成)
接上一篇:i.mx6 Android5.1.1 初始化流程之init进程 参考资料:http://blog.csdn.net/mr_raptor/article/category/799879 这个博 ...
- i.mx6 Android5.1.1 初始化流程之框架
Android启动过程分为以下几个步骤: 1. Boot ROM: 上电后启动芯片固话代码. 2. BootLoader:固话代码会根据启动模式启动bootloader,(一般为启动引脚的电平的 ...
- i.mx6 Android5.1.1 servicemanager本地服务
接在之前的 i.mx6 Android5.1.1 初始化流程之init进程 i.mx6 Android5.1.1 初始化流程之init.rc解析 servicemanager是由init创建的本地服务 ...
- i.mx6 Android5.1.1 System server
1. 概述: 1. Zygote进程是Android Java世界的开创者,所有的Java应用程序进程都由Zygote进程创建: 2. Zygote创建应用程序进程过程其实就是复制自身进程地址空间作为 ...
- Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)
View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇 ...
- activiti自定义流程之Spring整合activiti-modeler5.16实例(九):历史任务查询
注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 (2)创建流程模型:activiti自定义流程之Spring ...
- activiti自定义流程之Spring整合activiti-modeler5.16实例(八):完成个人任务
注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 (2)创建流程模型:activiti自定义流程之Spring ...
- activiti自定义流程之Spring整合activiti-modeler5.16实例(七):任务列表展示
注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 (2)创建流程模型:activiti自定义流程之Spring ...
- activiti自定义流程之Spring整合activiti-modeler5.16实例(六):启动流程
注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 (2)创建流程模型:activiti自定义流程之Spring ...
随机推荐
- 字节码执行方式--解释执行和JIT
此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.两种执行方式: 解释执行(运行期解释字节码并执行) 强制使用该模式:-Xint 编译为机器码执行(将字 ...
- django系列8.2--django的中间件流程
Django请求流程图 请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpRe ...
- 红与黑(DFS)
描述有一间长方形的房子,地上铺了红色.黑色两种颜色的正方形瓷砖.你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动.请写一个程序,计算你总共能够到达多少块黑色的瓷砖.输入包括多个数据集合.每个数据集 ...
- “全栈2019”Java异常第四章:catch代码块作用域详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- JAVA构造函数(方法)
一.什么是构造函数 java构造函数,也叫构造方法,是java中一种特殊的函数.函数名与相同,无返回值. 作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法. 在现 ...
- 【vim】简介与基本配置
vim是一款非常强大的文字编辑软件,是各种类UNIX系统标配的文本编辑工具.相信此文的读者对它应该不会陌生,在这里就不做介绍了. 1.为什么要使用vim 在认识vim之前,我用过好多IDE:Visua ...
- Python Socket 编程示例 Echo Server
简评:我们已经从「Python Socket 编程概览」了解了 socket API 的概述以及客户端和服务器的通信方式,接下来让我们创建第一个客户端和服务器,我们将从一个简单的实现开始,服务器将简单 ...
- Xcode 编译更改 Build 输出路径
Xcode新建一个工程,build之后,可执行文件一般在 ~/Library/Developer/Xcode/DerivedData 下. 可以把这个路径指定为当前工程目录.  指定方法 Xcode ...
- QuantLib 金融计算——数学工具之求解器
目录 QuantLib 金融计算--数学工具之求解器 概述 调用方式 非 Newton 算法(不需要导数) Newton 算法(需要导数) 如果未做特别说明,文中的程序都是 Python3 代码. Q ...
- 通过源码看原理之 selenium
# selenium的历史1. selenium1.x:这个时候的selenium,使用的是JavaScript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素 ...