Dim*_*imG 4 unix bash pipe file-descriptor
我有一个充满文件编号的文件(从0开始)
$ cat in.del
0
1
2
....
Run Code Online (Sandbox Code Playgroud)
有人能解释一下这里发生了什么以及除了管道之外缓冲发生在哪里吗?据我了解,两个head's
fileno(stdin) 都必须直接查看管道的读取端
$ cat in.del | ( head -n1 ; head -n1 )
0
60
Run Code Online (Sandbox Code Playgroud)
下面的代码与上面的代码有何不同?
$ cat in.del | ( head -n10 ; head -n10 )
0
1
...
8
9
60
1861 # O_o
1862
1863
...
1868
1869
Run Code Online (Sandbox Code Playgroud)
这按预期工作,并表明head
它本身读取的字节数不会多于实际写入其' 的字节数stdout
:
$ ( head -n10 ; head -n10 ) < ./in.del
0
1
...
9
10
11
...
18
19
Run Code Online (Sandbox Code Playgroud)
显然有一些与管道有关的事情发生
更新
操作系统:Ubuntu 18.04.1 LTS
Bash:版本 4.4.19(1)-release (x86_64-pc-linux-gnu)
更新 2 作为 @Barmar 精彩答案的补充,更多关于 stdio 缓冲的信息
发生的情况是 stdio 一次从管道读取整个缓冲区,Linux 上的缓冲区大小为 8K。
然后head
从缓冲区中读取前 10 行,打印它们,然后退出。
下一个head
开始从上一个停止的管道中读取 8K 字节到文件中。它读取该行和接下来的 9 行。你看到的60
就是 的结尾1860
。
它在最后一种情况下按预期工作的原因是因为head
在退出之前寻找它打印的最后一行的末尾。查找在管道中不起作用,因此这没有效果。但当stdin
是普通文件时,seek就起作用,下一个过程从seek设置的文件位置开始。
我在 Mac 上看到的结果略有不同。它的缓冲区大小为 64K,因此第二个head
在文件中开始的时间要晚得多。在退出之前它也不会返回到最后打印行的末尾,因此带有文件重定向的版本与管道的工作方式相同。
归档时间: |
|
查看次数: |
126 次 |
最近记录: |