The parsing of the pair is performed in parse_config(): [system/core/init/init_parser.c]. To analyze which stage of the entire init process occurs, refer to "Android init process startup process analysis".
1. Analytical process
1.
Find the end of the file EOF/text TEXT/new line NEWLINE, the spaces ‘ ', ‘\t', ‘\r’ will be ignored, and the lines starting from # will also be ignored;
For TEXT, spaces ‘ ', ‘\t', ‘\r', ‘\n' are all end signs of TEXT.
2. For each TEXT token, it is added to the args[] array
3. When a new line ('\n'), use args[0] to retrieve the matching keyword through lookup_keyword();
1) Call parse_new_section() to parse for Section (on and service):
- For on section, call parse_action() and set the parse function parse_line to parse_line_action()
- For service section, call parse_service() and set the parse function parse_line to parse_line_service()
2) Call parse_line() on lines of other keywords (not where the beginning of on or service, that is, there is no switching section)
That is,
- For the command line in the on section, call parse_line_action() to parse;
- For the command line in the service section, call parse_line_service() to parse.
2. Key data type prototype and key data definition
2.1 Definition of Token
[cpp]
#defineT_EOF 0
#defineT_TEXT 1
#defineT_NEWLINE 2
#defineT_EOF 0
#defineT_TEXT 1
#defineT_NEWLINE 2
2.2 Keyword definition
[cpp]
KEYWORD(capability, OPTION, 0, 0)
KEYWORD(chdir, COMMAND, 1, do_chdir)
KEYWORD(chroot, COMMAND, 1, do_chroot)
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1,do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
KEYWORD(console, OPTION, 0, 0)
KEYWORD(critical, OPTION, 0, 0)
KEYWORD(disabled, OPTION, 0, 0)
KEYWORD(domainname, COMMAND, 1, do_domainname)
KEYWORD(exec, COMMAND, 1, do_exec)
KEYWORD(export, COMMAND, 2, do_export)
KEYWORD(group, OPTION, 0, 0)
KEYWORD(hostname, COMMAND, 1, do_hostname)
KEYWORD(ifup, COMMAND, 1, do_ifup)
KEYWORD(insmod, COMMAND, 1, do_insmod)
KEYWORD(import, COMMAND, 1, do_import)
KEYWORD(keycodes, OPTION, 0, 0)
KEYWORD(mkdir, COMMAND, 1, do_mkdir)
KEYWORD(mount, COMMAND, 3, do_mount)
KEYWORD(on, SECTION, 0, 0)
KEYWORD(oneshot, OPTION, 0, 0)
KEYWORD(onrestart, OPTION, 0, 0)
KEYWORD(restart, COMMAND, 1, do_restart)
KEYWORD(service, SECTION, 0, 0)
KEYWORD(setenv, OPTION, 2, 0)
KEYWORD(setkey, COMMAND, 0, do_setkey)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
KEYWORD(trigger, COMMAND, 1, do_trigger)
KEYWORD(symlink, COMMAND, 1, do_symlink)
KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
KEYWORD(user, OPTION, 0, 0)
KEYWORD(wait, COMMAND, 1, do_wait)
KEYWORD(write, COMMAND, 2, do_write)
KEYWORD(copy, COMMAND, 2, do_copy)
KEYWORD(chown, COMMAND, 2, do_chown)
KEYWORD(chmod, COMMAND, 2, do_chmod)
KEYWORD(loglevel, COMMAND, 1, do_loglevel)
KEYWORD(ioprio, OPTION, 0, 0)
KEYWORD(capability, OPTION, 0, 0)
KEYWORD(chdir, COMMAND, 1, do_chdir)
KEYWORD(chroot, COMMAND, 1, do_chroot)
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1,do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
KEYWORD(console, OPTION, 0, 0)
KEYWORD(critical, OPTION, 0, 0)
KEYWORD(disabled, OPTION, 0, 0)
KEYWORD(domainname, COMMAND, 1, do_domainname)
KEYWORD(exec, COMMAND, 1, do_exec)
KEYWORD(export, COMMAND, 2, do_export)
KEYWORD(group, OPTION, 0, 0)
KEYWORD(hostname, COMMAND, 1, do_hostname)
KEYWORD(ifup, COMMAND, 1, do_ifup)
KEYWORD(insmod, COMMAND, 1, do_insmod)
KEYWORD(import, COMMAND, 1, do_import)
KEYWORD(keycodes, OPTION, 0, 0)
KEYWORD(mkdir, COMMAND, 1, do_mkdir)
KEYWORD(mount, COMMAND, 3, do_mount)
KEYWORD(on, SECTION, 0, 0)
KEYWORD(oneshot, OPTION, 0, 0)
KEYWORD(onrestart, OPTION, 0, 0)
KEYWORD(restart, COMMAND, 1, do_restart)
KEYWORD(service, SECTION, 0, 0)
KEYWORD(setenv, OPTION, 2, 0)
KEYWORD(setkey, COMMAND, 0, do_setkey)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
KEYWORD(trigger, COMMAND, 1, do_trigger)
KEYWORD(symlink, COMMAND, 1, do_symlink)
KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
KEYWORD(user, OPTION, 0, 0)
KEYWORD(wait, COMMAND, 1, do_wait)
KEYWORD(write, COMMAND, 2, do_write)
KEYWORD(copy, COMMAND, 2, do_copy)
KEYWORD(chown, COMMAND, 2, do_chown)
KEYWORD(chmod, COMMAND, 2, do_chmod)
KEYWORD(loglevel, COMMAND, 1, do_loglevel)
KEYWORD(ioprio, OPTION, 0, 0)
2.3 struct action and struct command
[cpp]
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 atrigger */
struct listnode tlist;
unsigned hash;
const char *name;
struct listnode commands;
struct command *current;
};
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 atrigger */
struct listnode tlist;
unsigned hash;
const char *name;
struct listnode commands;
struct command *current;
};
[cpp]
view plaincopyprint?
struct command
{
/* list of commands in an action */
struct listnode clist;
int (*func)(int nargs, char **args);
int nargs;
char *args[1];
};
struct command
{
/* list of commands in an action */
struct listnode clist;
int (*func)(int nargs, char **args);
int nargs;
char *args[1];
};
2.4 list action_list and action_queue
action_list
During parsing, on action is encountered and joined through act->alist;
queue_builtin_action() combines the executed function into command, creates an action, and hangs it on action_list.
action_queue
Execute action_for_each_trigger() and join through act->qlist;
queue_builtin_action() combines the executed function into command, creates an action, hangs it on action_list, and appends it to the tail of action_queue.
3. Analysis of action
Combining the init startup process and the analysis mentioned above, we will summarize the analysis of the init pair action.
3.1 Analysis of actions within section
When parse the new on section call parse_action() in 1.3.1, struct action *act is applied, and settings are set:
1) act->name is the name of the on section (such as boot/fs/);
2) Initialize list act->commands;
3) Add act->alist to the end of the column of action_list
In this way, the action is created and added to the action_list.
3.2 Analysis of command in action in section
Call parse_line_action() on the command in the action in the section
1) Find keywords, check whether it is COMMAND, and whether the number of parameters is correct
2) Apply for struct command *cmd
- cmd->func gets from the keyword table;
- Set the number of parameters to cmd->nargs, and copy the parameters to cmd->args;
- Add cmd->clist to the end of act->commands
In this way, command was added to the action.
3.3 Add action in action_list to action_queue
action_for_each_trigger() appends the action matched in the queue action_list to the tail of action_queue;
queue_builtin_action() combines the executed function into command, creates an action, hangs it on action_list, and appends it to the tail of action_queue.
3.4 Command execution
In Init's infinite loop execute_one_command():system/core/init/
1) Remove the structaction *act from action_queue and assign it to cur_action;
2) Obtain struct command from cur_action *assign to cur_command;
3) Execute cur_command->func(cur_command->nargs, cur_command->args)
In the above steps, 1, 2 & 3 are executed at one time, and 4 is executed infinitely. Remove the action from action_queue, get the command in the action, and then execute the command.
4. Grammar summary
There is a syntax description in system/core/init/Readme. When I did not analyze the init source code before, I also read this Readme file, but I don’t know much about the definition of some concepts. After the analysis, let’s try to sort out the grammar.
1. The line at the beginning is also ignored and used for commenting;
2. “', ‘\t', ‘\r’ will be ignored, so if the attribute contains spaces, the following will not be recognized; the indentation before command in each Action does not require syntax, but is only easy for people to read;
3. '\n' is a line break flag. In the init syntax, the beginning of new parsing is based on the beginning of a new line, and is analyzed line by line scan;
4. Some concepts: Section/Action/Command/Trigger
-
- It can be early-init/init/early-fs/fs/post-fs/early-boot/boot; it can also be property:<name>=<value>, when the value of the property <name> is set to <value>; device-added-<path>/ device-removed-<path> device node is joined or removed; service-exited-<name> service exits.
- When on <trigger> occurs, an action, that is, the part after on<trigger>, can contain multiple commands;
-
The form is as follows:
[cpp]
on <trigger>
<command>
<command>
<command>
on <trigger>
<command>
<command>
<command>This whole is a Section; all <command> is called action.
Summarize
The basic syntax analyzed in this article focuses on the analysis of on section, service analysis and property support will be discussed in detail in the subsequent topics.