安卓底层开发学习经验第十三期

这一期我们来看一下我们 init 进程是如何执行这些脚本,和创建服务、守护服务的。
首先来看一下 init 进程在后期所做的一些工作

当我们吧脚本解析完之后,就会把我们的解析结果放到两个结构中,一个是action_list ,一个是 service_list ,在解析完之后我们会使用我们的 action_for_each_trigger 来将解析脚本中的相关操作添加到我们的 action 队列中,添加完之后他会在后面创建服务和执行命令的时候,来对我们的 action_queue 进行操作,我们这里也提供了一个我们自己构建命令的一个函数( quene_builtin_action ),他是在我们代码中直接创建命令,并且添加到我们的 action_queue action_list 中,当把所有的启动命令构建完成之后,就开始一条一条的执行我们的启动脚本创建并且守护我们相关的服务。
那么下面我们来看一下我们解析完我们的启动脚本之后,我们的 service_list action_list 这两个队列的结构

我们的service_list action_list 其实就是一个双向链表,当我们解析完一个命令或者一个服务之后,他就会把我们的服务或者命令插入到我们的 service_list action_list 中,我们的 service_list 用来保存我们解析过程中的 service ,而我们的 action_list 就是把我们的相关操作命令给添加进来。
我们先来看一下 service_list ,他的节点全是我们 init 脚本中的一些服务,节点内容就是我们的服务的二进制文件以及执行的参数,在后面我们回家一下相关的参数,比如说他的 user group 等,都会在这里添加出来,所以说他的结构就是这样的,一个 service 连接这下一个 service ,一直到最后一个 service ,在每个 service 后面都会有一个相关的属性,这就是我们 service 的一个数据结构。
下面我们来看一下我们的 action_list ,他的节点都是我们 on 打头的一个 section ,在这个 section 下会有 n 个执行命令,比如我们的 mkdir write 等,一个 on 加我们的 early-init 或者 init post-fs 等他下面都会挂接几个命令,而这几个命令,他也是一个双向链表,添加在我们这个 on 的节点下面,而我们的 on init 下面也会有一个 cmd_list ,这就是我们解析完之后 action_list 的一个数据结构。
下面我们来看一下,我们 init 进程是如何处理这两个数据结构的,下面我们来看一下我们整个事件的列表

这个处理函数是由我们的action_for_each_trigger 决定的,他在这里面会有一个事件的名字,和一个执行的函数( on early-init func ),他的大概过程是这样的,首先要遍历我们的 action_list ,找到我们的 section ,比如我们现在的 section on early-init ,那么他首先要找到我们的 section ,这个 section 就是我们 node 的名字,当他和我们的 on early-init 一致的话,我们就是用 func 去执行我们的命令,这个 func 所做的事情就是将我们 section 下面所对应的 cmd_list 添加到我们的 action_queue 中,这样就完成了一次添加,如果我们后面要添加 on boot 的话,我们就去找 on boot cmd_list ,然后再将他的 cmd_list 添加到我们的 cmd_list 中,依次是 cmd_list1 cmd_list2...... 这样的话我们所有的操作都会添加到我们的 action_queue 中。
当我们添加完成之后,我们还可以添加一些自己的命令,比如在程序代码中写一些命令,那么我们可以使用 queue_builtin_action 这个函数,这个函数就是创建一个 action node ,并且将 action node 添加到我们的 action_list 和我们的 action_queue 中,当我们完成这一系列的添加之后,我们就可以交给我们的 init 进程来执行 action_queue 中的所有操作。
接下来我们来看一下 action_for_each_trigger 这个函数,我们打开我们的 init.c 文件,我们来看一下在我们 init.rc 解析完之后是如何处理的,首先我们看一下 action_for_each_trigger 这个函数

他呢就是根据我们的trigger 来找到我们的 section ,并且如果说我们的 trigger 和我们的 section 的名字是相同的,那么我们就是用 func 对我们的节点进行操作
下面我们再来看一下我们的 queue_builtin_action

这个函数的功能就是创建一个自己的 action ,并且把它添加到我们的 action_queue action_list 中,首先创建一个 action 的节点,将我们的函数指针以及名字赋值到我们的结构中,然后把它添加到 action_list action_queue 中,这就是构建一个自己的操作。
当我们的整个操作创建完之后,我们就会在我们 init 后面的执行过程中去一条一条的执行我们的操作。
下面我们打开我们的 init.rc ,看一下我们的 service 的定义

Service 会有一个名字,后面对应我们的执行程序,也有可能我们后面还会加一些启动参数,
在这个 service 下面还会有一些属性,属性包括 class 等, class 还会分为 class core class main
下面我们来看一下我们这个服务的类型,以及我们如何来一条一条的执行我们所有的操作
我们来看一下 service 的分类

Service 主要分为三类, class core  class main  class default
我们再来看 init 进程是如何来执行我们的命令的

首先我们的init 进程会调用我们的 execute_one_command ,去我们的 action_queue 队列中取一条命令,我们的一个命令其实对应的是 keyword ,我们的 keyword 是一个名字加属性,加我们的执行函数,加我们的执行参数,而我们的 keyword 又分好多种,根据我们的 func 分类,他可以分为 do_chdir  do_class_start  do_rmdir 等,当我们每取出一个命令之后,就会去做相应的操作,去创建目录,建立链接,设置环境变量等一系列操作,还有一个就是 do_class_start 操作,他后面会跟一个参数,这个在 init.rc 中是有体现的,当我们去执行他的时候,我们后面会跟一个服务类的名称,这个名称就会去调用我们的 service_for_each_class ,来对我们的 service_list 进行遍历,如果 do_class_start 后面跟的类名,和我们的服务某一个节点的名字相同的话,我们就会调用我们的 service_start ,去启动我们相关的服务,这就是我们服务启动的一个过程。
下面我们来看一下我们代码的具体实现
当我们构建完所有的 action_queue 之后呢,我们进入了一个 for 的死循环,在这里边就是执行我们的每一条命令,并且去守护我们的服务。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值