Bash 输入输出缓冲区

Posted 17岁boy想当攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bash 输入输出缓冲区相关的知识,希望对你有一定的参考价值。

最近在研究Linux内核,发现早期的Linux内核里的Configure脚本(也就是make config)是shell写的,使用Bash作为解释器,在Make里的config的规则调用有一段非常有意思的写法:

/bin/bash Configure < config.in

Configure是Linux内核自己的内核语言解析脚本,主要用来生成autoconfig.h这个宏配置文件的,我解析了一下它的源代码,主要的调用在这里:

while IFS='@' read raw_input_line

这里它用了read命令,read是从输入缓冲区里读取内容,而bash这段调用:<,这个符号在unix里是IO重定向符,它会将config.in文件里的内容重定向到bash里去,也就是重定向到bash的输入缓冲区里了,所以在使用read命令进行读取,read命令每次会从输入缓冲区里读取一行,每次读取一行后会将指针移动到下一行,读取到的内容会保存到raw_input_line变量里,然后进行解析并生成对应的宏

而里面的IFS变量是分隔符,用来控制其它代码的分割读取的,这里可以忽略掉

通俗易懂的来说调用bash时可以使用<来对bash设置stdin,标准输入缓冲区。

其实<是shell里面重定向流的符号,同时也有>符号,大多数情况下我们常用的是>

echo test > tt.txt

用来将标准输出即stdout重定向到tt.txt里,同理也可以使用<符号将标准输入重定向到某个文件里,这样我们调用一些从stdin读取的命令或者函数时都会从这个文件里进行读取

stdout、stdin这两个缓冲区都是平台提供的,取决于你的运行平台,比如你是在shell上面执行的程序,那么由shell提供这两个缓冲区,如果是CMD那么就是CMD提供这两个缓冲区

对于C语言程序来说仍然如此:

执行:

./a.out < tt.txt

运行时会发现scanf并没有阻塞等待我们输入,而是直接从tt.txt文件里读取了一行,打印结果就是:

test

scanf会在stdin指针指向的缓冲区里判断是否有内容,并以/n/r这些符号作为换行符来判断结尾

并且还需要值得注意的是,缓冲区是以文件内存映射的方式提供给应用程序的,也就是将文件读取到内存里,并将stdin指针指向这块内存,你对它进行的一切修改不会被保存到实际的文件里去。

同时stdin还带有成员变量:

stdin->_I0_read_ptr

stdin->_I0_read_end

当我们每次读取之后,都会将_I0_read_ptr指针进行挪移,挪移到读取的末尾,这取决于scanf、read这些函数的具体实现,这也就是为什么当进行文件重定向为stdin之后每次读取时都会读取到下一行的原因所在,当_I0_read_ptr与_I0_read_end进行重叠时也就是读取到了末尾,那么IO函数将会对缓冲区进行清空,也就是全部置0并将_I0_read_ptr挪移到首地址里去。

以上是关于Bash 输入输出缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

带你读懂bash一句话反弹shell

带你读懂bash一句话反弹shell

输入输出流

Linux c学习--从标准输入输出看流和缓冲区

Bash基本功能:输入输出重定向

stdout和stderr标准输出的区别