Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the running process of SHELL?

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article is to share with you what it is like to run SHELL. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

one。 Startup process

Shell.c is the file where the shell main function main is located. Therefore, the startup of shell can be thought of as starting from the shell.c file. The main workflow completed by the main function includes: checking the running environment of startup (whether it is started through sshd, whether it runs in emacs environment, whether it runs in cgywin environment, whether it is interactive shell, whether it is login shell, etc., and whether it is a memory leak check on the system, whether it is a restricted shell). Read the configuration file (the order is / etc/profile and (~ / .bash_profile OR ~ / .bash_login OR ~ / .profile), set the values of the global variables needed to run (current environment variable, name of shell, startup time, input / output file descriptor, relevant settings for language localization), process parameters and options (that is, with parameters and options such as-c-s-debugger) Set the value of parameters and options (the run_shopt_alist () function calls the shopt_setopt function to set the value of the option Bind the value of the $position parameter), and then enter the following different branches according to different startup parameters:

If you are only extending the parameters without executing the command, call the run_wordexp function to extend the parameters, and then call the exit_shell (last_command_exit_value) function to exit with the return value of the last command.

If shell is started in-c parameter mode, it is divided into two cases: first, if a string parameter is attached as the command to be executed, call run_one_command (command_execution_string) to execute the command attached to-c, and the parameter command_execution_string holds the string command value followed by-c. After execution, call exit_shell (last_command_exit_value) to exit. Second: if you expect the user to enter the command to be executed, jump to branch 3.

Setting shell_initialized to 1 indicates that shell initialization is complete. Call the function reader_loop () defined in eval.c to continuously read and parse user input, and if the reader_loop function returns, call exit_shell, (last_command_exit_value) to exit shell.

two。 Command parsing and execution process 1. The main related documents Eval.cCommand.hCopy_cmd.cExecute_cmd.cMake_cmd.c2. Shell command structure:

The following structure is used in shell to represent a command.

Typedef struct command {the type of enum command_type type; / * command * / int flags; / * tag bit, which will affect the execution environment of the command * / int line; / * which line the command starts from * / REDIRECT * redirects / * associated redirect operation * / union {/ * the following is a joint value that holds a specific "command body", which may be a for loop, a case condition, a while loop, etc. The characteristic of the union structure is that only one value is valid, so the following command types are juxtaposed, followed by comments * / struct for_com * For; struct case_com * Case; struct while_com * While for each command type. Struct if_com * If; struct connection * Connection; struct simple_com * Simple; struct function_def * Function_def; struct group_com * Group;#if defined (SELECT_COMMAND) struct select_com * Select;#endif#if defined (DPAREN_ARITHMETIC) struct arith_com * Arith;#endif#if defined (COND_COMMAND) struct cond_com * Cond;#endif#if defined (ARITH_FOR_COMMAND) struct arith_for_com * ArithFor # endif struct subshell_com * Subshell; struct coproc_com * Coproc;} value;} COMMAND

One of the key members is the federated union type value, which indicates the type of the command and gives pointers to save the specific contents of the command. From the optional values of this structure, there are 14 commands defined by shell, such as for loop, case condition, while loop, function definition, cooperative asynchronous command and so on.

Among them, through the analysis of all command execution paths, it is determined that the command of type simple is the most atomic command operation after command replacement, and the other types of commands are composed of several simple command.

After shell starts, no matter which of the 2 and 3 branches above, the function used in the final parsing command is the function defined in execute_cmd.c. Branch 1 does not involve command parsing, so I will not analyze it here.

3. The first case of Branch 2:

In the process of run_one_command (command_execution_string) execution, parse_and_execute (defined in evalstring.c) is called to parse and execute commands, and execute_command_internal functions are actually called in parse_and_execute to execute commands.

4. The second case of Branch 2 and Branch 3:

The reader_loop function calls the read_command function parsing command, the read_command function calls the parse_command () function for parsing, and parse_command () calls yyparse () in the parser y.tab.c (this function is automatically generated by yyac, so it is no longer followed up inside the function), save the command string of the parsed result in the global variable GLOBAL_COMMAND, and then execute the execute_command function (defined in execute_cmd.c). The execute_command function calls the execute_command_internal function to execute the command. At this point, the case of branch 2 and branch 3 is merged into the execution of execute_command_internal.

5. Execute_command_internal internal process:

This function is the actual operation function in the shell source code to execute the command. He needs to analyze the value members of the specific command structure passed in as operation parameters, and then call specific command execution functions for different value types to interpret and execute specific commands.

Specifically, if value is simple, the execute_simple_command function is directly called for execution, and execute_simple_command calls execute_builtin and execute_disk_command respectively according to whether the command is an internal command or an external command on disk, where execute_disk_command calls the make_child function for sub-process to execute external commands when executing external commands.

If value is of another type, the function of the corresponding type is called for branch control. For example, if value is for_commmand, that is, this is a for loop control structure command, the execute_for_command function is called. In this function, the elements in each operation domain are enumerated and the execute_command function is called again for analysis. Functions such as execute_for_command realize the expansion of a command and the function of flow control and recursive call to execute_command.

Therefore, the main flowchart from the start of the main function to the execution of the command can be shown in the following figure:

6. Function-level flowchart from startup to command interpretation:

In parentheses is the file where the function definition is located.

three。 Variable control 1. The main related documents variables.cvariables.h2. Important data structure

In BASH, a variable structure is mainly described by variable context and variable structure. The following are introduced respectively.

Variable context: context can be understood as scope, which can be understood according to the function scope and global scope in C language. Variables in a context are visible in this context.

Variable context structure definition:

If typedef struct var_context {char * name; / * name is empty, it stores the bash global context, otherwise it indicates the number of layers in the call stack of the local context * / int scope; / * context of the function named name, 0 represents the global context, and each function call to scope increments by 1 layer / int flags. / * flag bit set flags records whether the context is local, whether it belongs to a function, whether it belongs to an internal command, or whether it is temporarily established, etc. * / struct var_context * up; / * points to the previous context in the function call stack * / struct var_context * down; / * points to the next context in the function call stack * / HASH_TABLE * table / * hash table for all variables in the same context, that is, name-value pairs * /} VAR_CONTEXT

A structure that describes the scope of a variable. All variables in a context are stored in the table member of var_context.

Variables: variables in bash do not emphasize types and can be thought of as strings. Its storage structure is as follows

Typedef struct variable {char * name; / * points to the name of the variable * / char * value; / * points to the value of the variable * / char * exportstr; / * points to a string * / sh_var_value_func_t * dynamic_value shaped like "name = value". / * if it is a function that returns a dynamic value, such as $SECONDS or $RANDOM, the function pointer points to the function that generated the value. * / sh_var_assign_func_t * assign_func; / * if it is a callback function that needs to be called when a special variable is assigned, the function pointer value is saved here * / int attributes; / * read-only. The visible attribute * / int context; / * records which layer of the local variable stack in the accessible scope of the context variable belongs to * /} SHELL_VAR.

Since all variables are generally represented by strings, attributes attribute members are provided to modify the features of variables, such as att_readonly for read-only, att_array for array variables, att_function for functions, att_integer for integer class variables, and so on.

3. Mechanism of action

The execution of shell programs is accompanied by context switching, and the variable control in the shell source code is also based on this. Bind variables in a context.

For example, the initial default is the global context, which is called global, which contains the value of the variable passed in by the parameter of the main function or the configuration file. If you enter the execution of a function foo at this time, foo first obtains the variables to be exported from the global context, plus the newly added variables to form the context local variables of foo, and presses the context of foo into the call stack. At this point, the call stack looks like this.

Top of the stack: foo context (contains all local variables of the foo context)

Bottom of the stack: global global context (contains all global variables)

In order to explain the situation in more detail, assuming that the fun function is called in foo, fun first gets the variable to be exported from foo, adds its own newly added variable to form the context local variable of fun, and then presses the context of fun into the top of the call stack.

. This is the call stack that looks like this.

Top of the stack: fun context (contains all local variables of the fun context)

In the stack: foo context (contains all local variables of the foo context)

Bottom of the stack: global global context (contains all global variables)

At this point, assuming that the fun function is finished, the fun context is pop out of the stack, and all local variables are invalidated. The call stack again looks like this.

Top of the stack: foo context (contains all local variables of the foo context)

Bottom of the stack: global global context (contains all global variables)

The search order of variables: from the top of the stack to the bottom of the stack, that is, if there is no variable to be found in the context of the top of the stack, find its next context in the stack, and if the entire call stack is not found, the search fails. For example, if there is a PWD variable (the current work path) in the context of the top of the stack, the global PWD variable is not looked up, which ensures the correct semantics of the local variable coverage.

4. Special variables:

Several special variables are defined in bash, which means that some additional coherent work needs to be done after the variable has been modified. For example, after the variable TZ that represents the time zone is modified, you need to call the tzset function to modify the corresponding time zone settings in the system. Bash provides a callback function interface for this type of variable to call the callback function when its value changes. This can be compared to the trigger mechanism in the database. In bash, special variables are stored in a global array, special_vars. It is defined as follows:

Struct name_and_function {char * name;/* variable name * / sh_sv_func_t * function pointer of the callback function to be triggered when the variable value is modified * /}

This structure represents a special variable structure that is used to generate specialvars arrays. Callback functions are generally the way sv variable names are named.

Static struct name_and_function special_vars [] = {{"BASH_XTRACEFD", sv_xtracefd}, # if defined (READLINE) # if defined (STRICT_POSIX) {"COLUMNS", sv_winsize}, # endif {"COMP_WORDBREAKS", sv_comp_wordbreaks}, # endif {"FUNCNEST", sv_funcnest}, {"GLOBIGNORE", sv_globignore}, # if defined (HISTORY) {"HISTCONTROL", sv_history_control}, {"HISTFILESIZE", sv_histsize} {"HISTIGNORE", sv_histignore}, {"HISTSIZE", sv_histsize}, {"HISTTIMEFORMAT", sv_histtimefmt}, # endif#if defined (_ _ CYGWIN__) {"HOME", sv_home}, # endif#if defined (READLINE) {"HOSTFILE", sv_hostfile}, # endif {"IFS", sv_ifs}, {"IGNOREEOF", sv_ignoreeof}, {"LANG", sv_locale}, {"LC_ALL", sv_locale} {"LC_COLLATE", sv_locale}, {"LC_CTYPE", sv_locale}, {"LC_MESSAGES", sv_locale}, {"LC_NUMERIC", sv_locale}, {"LC_TIME", sv_locale}, # if defined (READLINE) & & defined (STRICT_POSIX) {"LINES", sv_winsize}, # endif {"MAIL", sv_mail}, {"MAILCHECK", sv_mail}, {"MAILPATH" Sv_mail}, {"OPTERR", sv_opterr}, {"OPTIND", sv_optind}, {"PATH", sv_path}, {"POSIXLY_CORRECT", sv_strict_posix}, # if defined (READLINE) {"TERM", sv_terminal}, {"TERMCAP", sv_terminal}, {"TERMINFO", sv_terminal}, # endif / * READLINE * / {"TEXTDOMAIN", sv_locale}, {"TEXTDOMAINDIR", sv_locale} # if defined (HAVE_TZSET) & & defined (PROMPT_STRING_DECODE) {TZ, sv_tz}, # endif#if defined (HISTORY) & & defined (BANG_HISTORY) {"histchars", sv_histchars}, # endif / * HISTORY & & BANG_HISTORY * / {"ignoreeof", sv_ignoreeof}, {(char *) 0, (sh_sv_func_t *) 0}} Thank you for reading! This is the end of this article on "how SHELL runs". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report