};
void list_init(struct listnode *node)
{
node->next = node;
node->prev = node;
}
void list_add_tail(struct listnode *head, struct listnode *item)
{
item->next = head;
item->prev = head->prev;
head->prev->next = item;
head->prev = item;
}
void list_remove(struct listnode *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
}
void queue_builtin_action(int (*func)(int nargs, char **args), char *name)//内建的action,也就是不在init.rc中。一个act有多个command。trigger就是act->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);
}
action_for_each_trigger("early-init", action_add_queue_tail);将所有early-init的act,放到action_queue的队列里。
在所有act链表准备好之后,在for(;;)里开始一行一行执行。execute_one_command
监听到
handle_property_set_fd --> property_set --> property_set --> queue_property_triggers --> queue_property_triggers --> action_add_queue_tail
这样execute_one_command 有又可以 act 执行对应的命令了。
都有在init.rc中的command比如,mkdir,chroot,是字符串,通过字符串映射到一个keywords,这是数组到下标,从而找到真正要执行到函数do_chroot。do_chroot会调用chroot
。chroot则是封装好到系统调用。