Android startup Process Analysis (eight) Resolve init.rc action

Source: Internet
Author: User

#############################################

This article is extremely ice original, reproduced please indicate the source

#############################################

The previous chapter describes the Android boot process, which needs to be parsed after the init.rc is loaded.

The parsing also executes different initialized files based on three different sections, namely Parse_action,parse_service,parse_import.

So, in this section, we're going to talk about how to parse the keyword of init.rc and its corresponding action and command from Parse_action.

As usual, let's take a look at this function implementation:

static void *parse_action (struct parse_state *state, int nargs, char **args) {    struct action *act;    if (Nargs < 2) {        parse_error (state, "actions must has a trigger\n");        return 0;    }    if (Nargs > 2) {        parse_error (state, "the actions may not be extra parameters\n");        return 0;    }    act = calloc (1, sizeof (*act)); Initialize struct action    act->name = args[1];  Assigns the name of the action    List_init (&act->commands);//Initializes the commands of the action, which is the internal linked list of the struct    list_init (& act->qlist);  Initialize the qlist structure to the internal list    list_add_tail (&action_list, &act->alist);//Use ListNode alist, The current structure is added to the list of action_list as Sentinel nodes,/        * XXX Add to Hash */    return act;
The contents of this initialization are all linked list operations.
For a better understanding, let's look at the body of Action:

struct Action {/        * node in List of all actions */    struct ListNode alist;  Use this listnode to add it to action_list/        * 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;};
Well, to summarize, after parse_action, the current action is added to the list of action_list as Sentinel nodes.

And it was initialized with commands and the chain list of the two structures inside the qlist.

In Parse_new_section, we see that the parse_line of the current state is set to parse_line_action when the initialization is complete.

    Case K_ON:        state->context = parse_action (state, Nargs, args);        if (state->context) {            state->parse_line = parse_line_action;            return;        }        Break
The function of parse_line_action () is executed when the command of the next action is executed.

Details are as follows:

<span style= "color: #333333;" >                if (kw_is (kw, section)) {                    state.parse_line (&state, 0, 0);                    Parse_new_section (&state, KW, Nargs, args);                } else {</span><span style= "color: #ff9966;" >                    state.parse_line (&state, Nargs, args); (Parse_line_action (&state, Nargs, args) </span> <span style= "color: #333333;" >                }</span>
The next step is to see the realization of parse_line_action:

static void Parse_line_action (struct parse_state* state, int Nargs, char **args) {struct command *cmd;  struct Action *act = state->context;    With State->context, you get the action int (*func) (int nargs, char **args) just being parsed;    int kw, N;    if (Nargs = = 0) {//judgment is NULL, if there is no command to execute, it returns return;   } kw = Lookup_keyword (Args[0]);        Get kw, the principle is the same as getting the section if (!kw_is (kw, command)) {//If this command is not an order, the error is returned.        Parse_error (state, "Invalid command '%s ' \ n", args[0]);    Return   }//Because under Action, only the command is executed, and the command is n = Kw_nargs (kw) already defined in keywords; It takes a few arguments to get this command from keywords, which is the third item in the initialization array, Nargs if (Nargs < n) {//If the required parameter is not met, an error Parse_error is returned (the state , "%s requires%d%s\n", Args[0], n-1, n > 2?        "Arguments": "argument");    Return   } cmd = malloc (sizeof (*cmd) + sizeof (char*) * Nargs);   Initializes the command structure body in the action's structure cmd->func = kw_func (kw); Get the function that this command needs to execute and put it in the pointer of funcFace Cmd->line = state->line;  Get this command is the line in the file Cmd->filename = state->filename;  Which file is the commands Cmd->nargs = Nargs; The parameters of this commands are several memcpy (Cmd->args, args, sizeof (char*) * Nargs); Copy these parameters into the commands array list_add_tail (&act->commands, &cmd->clist); Add the currently executing commands to the action's structure, ListNode to the list of commands}

There is a question here, the action of the structure, the initialization of a qlist, but it does not seem to use AH?

What is this for?

Let's go back to the main function of init.c and look at:

    Init_parse_config_file ("/init.rc");    ERROR ("Action for each trigger  <==== Chao");    Action_for_each_trigger ("Early-init", Action_add_queue_tail);
After parsing the init.rc file, the Action_for_each_trigger function is executed.
void Action_for_each_trigger (const char *trigger,                             Void (*func) (struct action *act)) {    struct listnode *node;    struct action *act;    List_for_each (node, &action_list) {//From the previous action_list (all action), traverse.        act = node_to_item (node, struct action, alist);         if (!strcmp (Act->name, Trigger)) {  //if the first name and "trigger" have the same words, the Action_add_queue_tail function            Func (ACT) will be executed; In essence, the Action_add_queue_tail (ACT) function}}    

Let's take a look at what this function does:

void Action_add_queue_tail (struct action *act) {    if (List_empty (&act->qlist)) {        List_add_tail (& Action_queue, &act->qlist);}    }
Because each action is initialized with Qlist, it is definitely not empty.

Instead, the action structure is added to the action_queue linked list. It's strange why an action is added to two lists?

And go back to the main function of init.c,

As you can see, after the Action_for_each_trigger is over, a lot of operations have been done.

    Action_for_each_trigger ("Early-init", action_add_queue_tail);    Queue_builtin_action (wait_for_coldboot_done_action, "Wait_for_coldboot_done");    Queue_builtin_action (mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");    Queue_builtin_action (keychord_init_action, "Keychord_init");    Queue_builtin_action (console_init_action, "Console_init");    ERROR ("Action for each trigger init  <==== Chao");    /* Execute all the boot actions to get us started *    /Action_for_each_trigger ("Init", action_add_queue_tail);
And what does that queue_builtin_action do? Does it have anything to do with the question before us?

Take a look at its implementation:

void queue_builtin_action (int (*func) (int nargs, char **args), char *name)//Take the first function as an example, where Func is Wait_for_coldboot_done_    Action, name is wait_for_coldboot_done{struct action *act;    struct command *cmd;  act = calloc (1, sizeof (*act));  Initializes the structure of the action act->name = name;  Assigns the name List_init (&act->commands) to the structure of the action;  Initialize the command's linked list list_init (&act->qlist);  Initialize Qlist's linked list cmd = calloc (1, sizeof (*cmd));  The structural body of malloc command cmd->func = func;  Assign function to Cmd->func cmd->args[0] = name;  Set the first parameter of CMD to the name Cmd->nargs = 1;  For such functions, args and Nargs are useless, simply initialized, so that they are not null list_add_tail (&act->commands, &cmd->clist); Use command ListNode for clist nodes, <span style= "FONT-SIZE:13.63636302948PX; line-height:25.9943180084229px; font-family:arial; " > adds the currently executing commands to the action's structure, listnode the list of commands </span> List_add_tail (&action_list, &act- >alist); Add this action to Action_list's list action_add_queue_tail (aCT); Add this action to the Qlist node}

In this way, we can clearly see the difference between the two linked lists.

For this list of action_list, if the action in Init.rc is Action1,action2,action3 ... , then the list we action_list is:

Action_list, Action1, Action2, Action3, Actoin4 ..... wait_for_coldboot_done O_linux_rng .....

As for the linked list of action_qlist, the corresponding is:

action_queue , Early-init, Wait_for_coldboot_done, mix_hwrng_into_linux_rng, ...-& Gt MIX_HWRNG_INTO_LINUX_RNG, Property_service_init, init .... .


That is, Action_list is arranged in the order in which the init.rc is parsed, plus the action declared in init.c to add.

The Action_queue is arranged in a sequential process that is executed exactly as declared in the main function of init.c.

These have finally figured out the parsed data structure of the action, so another big challenge is the service data structures.

Let's take a look at the next article.



Android startup Process Analysis (eight) Resolve init.rc action

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.