糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > linux read函数_Linux中shell输入ls命令后会系统会发生什么

linux read函数_Linux中shell输入ls命令后会系统会发生什么

时间:2020-06-02 19:52:03

相关推荐

linux read函数_Linux中shell输入ls命令后会系统会发生什么

大家都用过Shell执行一些Linux命令

在命令的背后,到底发生了什么呢,让我们来一起探索

Shell执行主流程

1.Printthe info of reminding 打印提示信息

2.Waitinguser for input(wait) 等待用户输入

3.Acceptthe command 接受命令

4.Interpretthe command 解释命令

5.Findit,execute it, if have the parameter, the command interprete it 找到该命令,执行命令,如果命令含有参数,输入的命令解释它

6.Executefinished, back to the first step 执行完成,返回第一步

图示

shell的执行具体过程

我们把情况分为四类

非内置命令和内置命令

内置命令会改变shell的参数,比如cd, echo,exit等。内置命令实际上shell程序的一部分,其中包含的是一些比较简单的linux系统命令,这些命令由shell程序识别并在shell程序内部完成运行。通常在linux系统加载运行时shell就被加载并驻留在系统内存中。内置命令是写在bashy源码里面的,其执行速度比外部命令快,因为内部命令shell不需要创建子进程。

非内置命令他不会改变shell的参数,比如ls。非内置命令是linux系统中的实用程序部分,因为实用程序的功能通常都比较强大,所以包含的程序量很大,在系统加载时并不随系统一起被加载到内存中,而是在需要的时候才将其调入内存。通常非内置命令的实体并不包含在shell中,但是其命令执行过程是由shell控制的。shell程序管理非内置命令执行的路径查找、加载存放、控制命令的执行。非内置命令是在bash之外安装的,通常放在/bin、/usr/bin,/sbin、/usr/bin等下面。

一般而言,which命令能够查到的命令都是非内置命令。还有type也可以判别内置和非内置命令。

对于非内置命令,比如ls,它的执行过程如图:

对于非内置命令,父shell先fork一个子shell,然后子进程去执行bash的代码,从文本中一行一行的读取命令,然后再派生一个孙子进程去执行这些命令。

source和”.”命令

先来看一个例子:

会发生这样的现象是因为”./test.sh”它是被fork出来的子shell执行的,所以不会影响到父shell。而”source”和”.”命令都是shell的内置命令,他会在当前shell下执行。source还有一个功能就是使得配置文件立即生效,不用重启直接source运行一下就生效。

{}和()命令

{}和()都是成组命令,里面可以运行多条命令,但是他们的区别又是什么呢?

可以看到{}会让当前交互式shell去执行命令,而()会让子shell去执行命令。

解析

bash的入口函数main()位于文件shell.c中

intmain (argc, argv, env) int argc;char **argv, **env;{ .... shell_initialize (); .... run_startup_files (); .... shell_initialized = 1; /* Read commands until exit condition. */ reader_loop (); exit_shell (last_command_exit_value); }

main函数前部分主要做初始化工作,初始化完成之后,进入eval.c中的交互循环函数reader_loop()(shell.c中799行)。该函数不断读取和执行命令,直到遇到EOF。

此时函数调用关系为:main()–>reader_loop()。

/* Read and execute commands until EOF is reached. This assumes that the input source has already been initialized. */intreader_loop (){ .... if (read_command () == 0) {.... } else if (current_command = global_command) {....execute_command (current_command); } .... return (last_command_exit_value);}

reader_loop()函数中调用read_command()取得命令结构体global_command,然后赋值给current_command并交给execute_command ()去执行。

read_command ()调用parse_command (),此时函数调用关系为:main()–>reader_loop()–>read_command()–>parse_command()

/* Read and parse a command, returning the status of the parse. The command is left in the globval variable GLOBAL_COMMAND for use by reader_loop. This is where the shell timeout code is executed. */intread_command (){ .... result = parse_command (); .... return (result);}..../* Call the YACC-generated parser and return the status of the parse. Input is read from the current input stream (bash_input). yyparse leaves the parsed command in the global variable GLOBAL_COMMAND. This is where PROMPT_COMMAND is executed. */intparse_command (){ .... r = yyparse (); if (need_here_doc)gather_here_documents (); return (r);}

parse_command()调用y.tab.c中的yyparse ()函数,并使用函数gather_here_documents ()处理here document类型的输入重定向。

yyparse ()由YACC通过parse.y生成,函数内使用大量的goto语句,可读性较差:

intyyparse (){ .... yychar = YYLEX; .... yytoken = YYTRANSLATE (yychar); .... yyn += yytoken; .... switch (yyn) {case 2: { global_command = (yyvsp[(1) - (2)].command); .... } break;case 3: { global_command = (COMMAND *)NULL; .... } break;....case 6: { (yyval.word_list) = make_word_list ((yyvsp[(1) - (1)].word), (WORD_LIST *)NULL); } break;....default: break; } .... return YYID (yyresult);}

函数内调用yylex()(宏定义:#define YYLEX yylex ())来获得并计算出整型变量yyn的值,然后根据不同的yyn值获取具体的命令结构体。

在函数yylex()内部,调用read_token()获得各种类型的token并进一步调用read_token_word()获取具体的不同类型的单词结构WORD_DESC。

之后在yyparse()中,调用文件make_cmd.c中各种函数,根据yylex()获得的各种token和word组装成具体command。

此时的函数调用关系为:

main()–>reader_loop()–>read_command()–>parse_command()–>yyparse()–>yylex()–>read_token()——>read_token_word()————>global_command

如果觉得《linux read函数_Linux中shell输入ls命令后会系统会发生什么》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。