Android启动流程分析(十) action的执行和service的启动

for(;;) {int nr, i, timeout = -1;execute_one_command();restart_processes();….. }这个for循环的处理有很多,但是我们现在暂时关心的只有这短短的两个函数。execute_one_command();

restart_processes();

首先我们来分析execute_one_command函数,看着个函数的名字,我们就能明白这个函数的功能。

这个函数就是去执行一个command嘛。。

来看一下这个函数的实现:

void execute_one_command(void){int ret, i;char cmd_str[256] = "";if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) { // 在第一次的启动中,因为都是NULL,所以肯定可以进入这个判断,如果不是第一次的话,因为得到cur_action或者cur_command都是null,并且如果这个command是当前action的最后一个command的话,会进入到下面的这个判断。cur_action = action_remove_queue_head(); // 依次获取action从action_queue中cur_command = NULL; // 在获取新的action之后,将cur_command设置为nullif (!cur_action) // 如果没有action了,则返回return;INFO("processing action %p (%s)\n", cur_action, cur_action->name);cur_command = get_first_command(cur_action); // 如果是一个新的action的话,会执行到这一步去获得first command} else {cur_command = get_next_command(cur_action, cur_command); // 仍然在action的内部链表中,如果仍然存在没有被获取到的command的话,则会去获得下一个command。}if (!cur_command) // 如果获取到的command为空的话,会返回,反之,继续return;ret = cur_command->func(cur_command->nargs, cur_command->args); // 会调用这个command的func区执行,执行的参数个数为nargs,命令为argsif (klog_get_level() >= KLOG_INFO_LEVEL) { // Log的打印for (i = 0; i < cur_command->nargs; i++) {strlcat(cmd_str, cur_command->args[i], sizeof(cmd_str));if (i < cur_command->nargs – 1) {strlcat(cmd_str, " ", sizeof(cmd_str));}}INFO("command '%s' action=%s status=%d (%s:%d)\n",cmd_str, cur_action ? cur_action->name : "", ret, cur_command->filename,cur_command->line);}}其实这个逻辑是比较好理解的,我们要着重分析的仅仅是如何获取action以及command.

来看一下action_remove_queue_head这个函数:struct action *action_remove_queue_head(void){if (list_empty(&action_queue)) { // 首先我们去判断当前待执行的action是否已经为null,即是否还有action没有被执行return 0;} else {struct listnode *node = list_head(&action_queue); // 如果仍然有未被执行的队列的话,就将node指向现在action_queue的头指针struct action *act = node_to_item(node, struct action, qlist); // 取出actionlist_remove(node); // 将这个节点从整个action _queue的列表中删除list_init(node); // 删除这个节点后,为了安全起见,将node自己指向自己,以避免出现野指针。return act; // 返回已经查找到的action}}我们可以看到,其实是从action_queue中拿每一个结构体的。

在拿到action之后呢?就要从action里面去拿command了。

来看一下下面的这两个函数:static struct command *get_first_command(struct action *act) // 从一个actoin里面寻找其第一个command,所以只用传递action即可{struct listnode *node;node = list_head(&act->commands); // 将node指向action的commands的结构体if (!node || list_empty(&act->commands)) // 如果这个节点不存在,或者这个action的commands结构体为空,则返回nullreturn NULL;return node_to_item(node, struct command, clist); // 返回第一个节点}static struct command *get_next_command(struct action *act, struct command *cmd) // 返回当前commands的下一个command{struct listnode *node;node = cmd->clist.next; 指针向后移动nextif (!node) // 如果不存在,则返回nullreturn NULL;if (node == &act->commands) // 如果这个节点已经是头节点了,则返回nullreturn NULL;return node_to_item(node, struct command, clist); // 返回next节点}在获取到了command之后,我们会去调用command的方法:

ret = cur_command->func(cur_command->nargs, cur_command->args);去执行command里面的每一个func。

但是,非常奇怪的是,执行完commands之后,service是怎么启动的呢?

我们再去init.rc里面一探究竟。

<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; background-color: rgb(240, 240, 240);">on boot….class_start core</span>on nonencryptedclass_start mainclass_start late_start我们看到在action里面,,会有一些commands是class_start, 而后面跟的参数,好像与我们service的class name 是一致的。再回到init.rc里面看看service的部分呢?

service adbd /sbin/adbd –root_seclabel=u:r:su:s0class coresocket adbd stream 660 system systemdisabledseclabel u:r:adbd:s0# adbd on at boot in emulatoron property:ro.kernel.qemu=1start adbdservice lmkd /system/bin/lmkdclass corecriticalsocket lmkd seqpacket 0660 system systemservice servicemanager /system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart restart healthdonrestart restart zygoteonrestart restart mediaonrestart restart surfaceflingeronrestart restart drm从keywords里面,我们找到了对应的function:

./init/keywords.h:53: KEYWORD(class_start, COMMAND, 1, do_class_start)来看一下do_class_start的实现:

int do_class_start(int nargs, char **args){/* Starting a class does not start services* which are explicitly disabled. They must* be started individually.*/service_for_each_class(args[1], service_start_if_not_disabled);return 0;}这个函数的实现很简单,仅仅是传递调用了service_for_each_class, 并且在传递service name的时候,多传递了一个参数为service_start_if_not_disable.

有希望在的地方,痛苦也成欢乐

Android启动流程分析(十) action的执行和service的启动

相关文章:

你感兴趣的文章:

标签云: