Android之init进程分析(1)

本文介绍init进程中的action触发方式

一,什么是action

在android中,使用action来管理并执行命令。action是一个数据结构,里面包含了命令集合command,action的名字等。Android系统通过action来执行一组命令。

struct action {
/* node in list of all actions */
struct listnode alist;
/* node in the queue of pending actions */
struct listnode qlist;
/* node in list of actions for a trigger */
struct listnode tlist;

unsigned hash;
const char *name;

struct listnode commands;
struct command *current;
};

所有的action都是通过alist组成一个链表(action_list),通过qlist组成一个执行队列(action_queue),tlist暂时没有用到。action里面的所有命令,以struct command的结构存放在commands为头的链表中;current指向当前的命令。

struct command
{
/* list of commands in an action */
struct listnode clist;

int (*func)(int nargs, char **args);
int nargs;
char *args[1];
};

上面的command结构体中,用clist来链接action下面的所有命令,命令包含了函数func,参数个数nargs,以及参数args。

有两个链表头,来链接action们:

static list_declare(action_list);

static list_declare(action_queue);

其中第一个为action链表头,第二个为action执行链表头。从init.rc配置文件中读出来的以及代码中设置的action,首先加入到action_list链表中,然后根据启动时机(init,boot阶段等)把需要执行的action加入到action_queue中。在init的主循环中,action_queue中的命令得到执行。

二,action是如何添加的

有两种方式把action添加到action_list和action_queue链表中,第一种为init.rc中配置,在init进程启动过程中解析init.rc配置文件;另外一种为代码中调用函数添加。

首先介绍第一种方式。 init进程启动时,会读取init.rc(以及init.xxxx,rc,xxxx为设备名字)配置文件。init.rc定义了专门的格式,分为三种类型:命令(action),服务(service),导入(import),比如:

on early-init

start ueventd

service ueventd /sbin/ueventd
class core
critical

import init.test.rc

如上,以on开头的标志了action开始,early-init为action的名字,下面的start ueventd为action的命令,可以有多条命令,直到遇到其他类型的定义关键字(这里是遇到service)为止。以service开头标志了服务,service后面的为服务名字和服务可执行程序,下面的class core等,为uevented服务的属性,可以有多条属性,直到遇到其他类型为止。import导入其他的文件。

在init进程中,先把配置文件读入到内存中 ,然后调用int init_parse_config_file(const char *fn)函数来解析配置文件,把on开头的读入到action结构体中,其后面的命令读入到command结构体中,并链接到action中。然后把action结构链接到action_list表头中。

之后通过调用action_for_each_trigger(“early-init”, action_add_queue_tail)等函数把名称为early-init的action加入到action_queue中。

除了解析配置文件构建action之外,代码中也可以通过调用queue_builtin_action来添加action到action_list和action_queue中:

void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
{
struct action *act;
struct command *cmd;

act = calloc(1, sizeof(*act));
act->name = name;
list_init(&act->commands);

cmd = calloc(1, sizeof(*cmd));
cmd->func = func;
cmd->args[0] = name;
list_add_tail(&act->commands, &cmd->clist);

list_add_tail(&action_list, &act->alist);
action_add_queue_tail(act);
}

void action_add_queue_tail(struct action *act)
{
list_add_tail(&action_queue, &act->qlist);
}

函数申请了action和command的内存空间,然后链接到action_list和action_queue中。

三,action的执行

action_list里面包含了一系列的action,并且按照一定次序添加到了action_queue队列中。接下来需要从action_queue中读取action,并且依次执行里面的command。

init的主循环中,做了命令的执行动作:

for(;;) {
int nr, i, timeout = -1;

execute_one_command();
restart_processes();

……….

if (!action_queue_empty() || cur_action)
timeout = 0;

……….

nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;

……….,

}

如上,execute_one_command调用只执行了一个command命令,如果执行完整个action的所有命令,则把此action从action_queue中删除。事实上,init进程开始的时候,加入了很多action到队列中,因此需要反复循环调用execute_one_command才能够执行完成。

通过action_queue_empty调用来控制循环,当action_queue不为空的时候,代码设置了timeout = 0,这样会导致poll(ufds, fd_count, timeout)调用立即返回,而不是以阻塞 方式等待。所以一旦有action加入到action_queue队列中,整个for循环就会轮回多次,多次执行execute_one_command,直到action_queue为空。

时间: 2024-07-30 20:29:28

Android之init进程分析(1)的相关文章

android init进程分析

android的init进程用来启动zygote进程,用来启动android世界.init进程的源码在顶层目录的/system/core/init使用 find -name Android.mk -exec grep -l "init" {} \;来查找源码,接下来的android服务程序也是使用这个指令来查找源码. /system/core/init/init.c 整个init进程的入口函数669 int main(int argc, char **argv) init_parse_

android init进程分析 基本流程

(懒人最近想起我还有csdn好久没打理了,这个android init躺在我的草稿箱中快5年了,稍微改改发出来吧) android设备上电,引导程序引导进入boot(通常是uboot),加载initramfs.kernel镜像,启动kernel后,进入用户态程序.第一个用户空间程序是init, PID固定是1.在android系统上,init的代码位于/system/core/init下,基本功能有: 管理设备 解析并处理启动脚本init.rc 实时维护这个init.rc中的服务 init进程的

Android Init进程分析番外篇:9.0的init进程

1 前言 在之前的几篇文章中,我们基于Android 4.4源码分析了init进程的启动及事件处理逻辑.目前Android版本已然更新到Android 10了,很多代码及服务架构都做了大范围的调整重构,这其中也包括init相关的代码. 但是,万变不离其宗,很多核心思想和处理逻辑Android还是都保留了下来,只是在写作上做了更好的功能封装和逻辑分割. 接下来笔者就非常简略的说一下Android 9.0 的init进程. 2 Android 9.0 init 分析 对于9.0的init笔者不想做过

android init进程分析 init脚本解析和处理

(懒人近期想起我还有csdn好久没打理了.这个android init躺在我的草稿箱中快5年了.略微改改发出来吧) RC文件格式 rc文件是linux中常见的启动载入阶段运行的文件.rc是run commands的缩写.基本上能够理解为在启动阶段运行的一些列命令.android init进程启动时,也会运行此启动脚本文件,init.rc.init.rc的写法稍有点复杂,具体可參考 /system/core/init下的readme文件.脚本基本组成是由四类,为: commands: 命令 act

Android 4.4 Init进程分析二:init.rc文件的解析

国际惯例,我们先看一下源码: http://androidxref.com/4.4_r1/xref/system/core/init/init.c#1039 1 init_parse_config_file("/init.rc"); 在init进程的main()函数里,会调用init_parse_config_file()方法解析init.rc脚本,注意这里传递的参数是根目录下的 "/init.rc"文件路径. init_parse_config_file()方法定

构建根文件系统之init进程分析

busybox是ls.cp等命令的集合. 执行ls时,实际上是执行了busybox ls 执行cp时,实际上是执行了busybox cp 分析init程序之前,再让我们回想一下我们的目标:u-boot启动内核,内核启动应用程序,内核是怎样启动应用程序呢,内核启动了init进程,位于/sbin/init中.我们最终的目的是启动客户程序,也就是说假如你是做手机的,希望启动一个手机的程序,假如是做监控的,那么就启动一个监控的程序的.客户各有不同,但都使用了linux系统,那么怎样加以区分呢? init

android init进程分析 ueventd

转自:http://blog.csdn.net/freshui/article/details/2132299 (懒人最近想起我还有csdn好久没打理了,这个Android init躺在我的草稿箱中快5年了,稍微改改发出来吧) ueventd主要是负责设备节点的创建.权限设定等一些列工作.服务通过使用uevent,监控驱动发送的消息,做进一步处理.ueventd实际和init是同一个binary,只是走了不同分支,可参看前一部分. ueventd的整体代码比较简单,主要是三部分: 解析ueven

android之init进程-uevent

转载! Init是linux kernel启动的第一个进程,理解init,对熟悉android系统非常重要. Android的每个目录下面都有一个非常重要的文件Android.mk,负责编译该目录下面的代码. System/core/init/android.mk [cpp] view plaincopy <span style="font-size:18px;"> </span><span style="font-size:18px;"

Android之rild进程启动源码分析

Android 电话系统框架介绍 在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP.AP与BP之间有两种通信方式: 1.Solicited Response:Ap向Bp发送请求,Bp给Ap发送回复,该类型的AT指令及其回调函数以数组的形式存放在Ril_commands.h文件中: {数组中的索引号,请求回调函数,响应回调函数} [plain] view plaincopy {0, NULL, NULL},