文档章节

鸟人的Android揭秘(14)——Init进程源代码分析(五)

 鸟人部落
发布于 2017/01/22 18:43
字数 1294
阅读 51
收藏 0

      前一篇主要讲解了init进程如何创建套接字以处理子进程终止,接下来我们继续分析init进程启动属性服务,以及分析init.rc的过程。

      接下来init进程需要设置系统属性,如代码3-16所示。

property_load_boot_defaults();
export_oem_lock_status();

代码 3-16 main()-设置系统属性

      property_load_boot_defaults()函数实际上就是调用load_properties_from_file()[1]函数解析“/default.prop”配置文件,然后根据解析的结果设置系统属性。export_oem_lock_status()函数根据系统状态设置“ro.boot.flash.locked”属性。这部分代码较为简单,不深入分析。

      然后启动属性服务,它是init进程最主要的功能之一。init进程在共享内存区域中,创建并初始化属性域。其它进程可以访问属性域中的值,但更改属性值仅能在init进程中进行。其它进程修改属性值时,要预先向init进程提交属性值变更申请,然后init进程处理该申请并修改属性值。在访问和修改属性时,init进程都可以进行权限控制。

start_property_service();

代码 3-17 main()-启动属性服务

      如前所述,属性值的更改仅能在init进程中进行,为此init进程生成“/dev/socket/property_service”套接字,以接收其它进程提交的申请。

      接下来init进程开始解析init.rc文件并执行相关的命令。init.rc文件大致分为两大部分,一部分是以“on”关键字开头的动作列表(Action List),另一部分是以“service”关键字开头的服务列表(Service List)。动作列表用于创建所需目录,以及为某些特定文件指定权限,而服务列表用来记录init进程需要启动的一些子进程。此外,还有一个关键字“import”,用于导入另外一个.rc文件,解析生成动作列表和服务列表,这些列表会分别被添加到init.rc文件已生成的服务列表和动作列表中。

      代码3-18所示创建了init.rc所需的解析器(Parser),用于解析“service”、“on”、“import”等关键字开始的列表。

const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());

代码 3-18 main()-创建init.rc解析器

      然后便开始解析init.rc文件。init.rc文件是在init进程启动后执行的启动脚本,文件中记录着init进程执行的功能。在Linux系统中,它被定义在根文件系统的“/etc/rc.d/”目录下,是启动时的可执行文件,在“/etc”目录下保存着设置环境变量的脚本。但在Android系统中,仅使用init.rc与init.{hardware}.rc两个文件,init.rc文件在Android系统运行过程中用于通用的环境设置及进程相关的定义,init.{hardware}.rc用于定义Android在不同平台下的特定进程和环境设置等。

parser.ParseConfig("/init.rc");

代码 3-19 main()-解析init.rc文件

      ParseConfig()方法传入参数是“/init.rc”,解析运行时与init进程同在根目录下的init.rc[2]文件。ParseConfig()方法实质上是调用ParseData()方法进行解析。执行该方法,读取并分析init.rc文件后,生成服务列表与动作列表。相对以前的代码,在Android 7.0的代码中,init.rc文件的解析已经做了较好的封装,动作列表解析后保存在ActionManager[3]类的actions_向量中,类似的,服务列表保存到ServiceManager[4]类的services_向量中。

      init进程会依次执行“early-init,init,late-init”片段中的命令,如代码3-20所示,init进程利用参数构造EventTrigger,然后加入到trigger_queue_中,后续init进程处理trigger事件时,将会触发相应的操作。init进程在后续代码依次构造了“early-init”、“init”、“late-init”的事件触发器,代码仅以构造“early-init”触发器为例。

am.QueueEventTrigger("early-init");

代码 3-20 main()-向执行队列中添加命令

      下面的代码构造新的action加入到actions_中,第一个参数作为新建action携带cmd的执行函数;第二个参数既作为action的trigger name,也作为action携带cmd的参数。

// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");

代码 3-21 main()-构造新的Action

      init进程在紧接着还会构造几个action,使用方法与上述代码非常类似,此处不再赘述。下一篇我们将讲解init进程如何处理上文构造出来的这些trigger、action和service。

 

[1] load_properties_from_file()函数定义在system/core/init/property_service.cpp。

[2] init.rc文件在编译前,定义在system/core/rootdir/init.rc中。

[3] ActionManager定义在system/core/init/action.h中。

[4] ServiceManager定义在system/core/init/service.h中。

© 著作权归作者所有

粉丝 1
博文 14
码字总数 16642
作品 0
海淀
私信 提问
鸟人的Android揭秘(2)——通过启动过程分析 Android Framework

Android源代码数量极其庞大,以最新的 Android 7.1 为例,代码数量超过 50G。若想理解和掌握如此庞大的 Android 系统,将需要耗费大量的时间和精力,付出极大的努力。关键是到目前为止也没有...

鸟人部落
2016/12/12
24
0
鸟人的Android揭秘(9)——Init进程运行过程

众所周知,Linux中所有进程都是由init进程创建并运行起来的。首先Linux加载内核启动,然后在用户空间中启动init进程,之后init进程再依次启动系统运行的其它进程。在系统启动完成后,init进程...

鸟人部落
2016/12/25
29
0
cocos2d-x支持c++、js、lua开发

作者:左文 链接:https://www.zhihu.com/question/21130385/answer/21789568 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 纯属个人观点 1 Unity3d支...

壹峰
2017/10/18
174
0
android手机打电话代码分析

Linux手机打电话代码分析(Android) Android 2009-03-16 17:02 阅读705 评论0 字号: 大大 中中 小小 Android源代码分析之电话功能 RIL 根据:《Android 源码分析-打电话和发短信》一文(时...

迷糊
2009/10/10
7.8K
1
Android 进阶学习笔记整理

一.android系统架构图及各层介绍 1. 应用层:应用是用java语言编写的运行在虚拟机上的程序,比如通讯录,日历,电话,短信,浏览器等。 2. 应用框架层:这一层是编写Google发布的核心应用时所...

FunCode
2018/07/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
6
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
1K
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部