无缓冲通常对输出更有意义。输出缓冲是应用程序在写入之前保留其输出的地方,直到它累积到足够的数量以最小化 I/O 的数量。
在输入时,应用程序所能做的就是调整它一次从输入中读取的字节数(好吧,它至少请求,因为它不能保证接收到那么多;文件可能有更少的可用字节,例如用于管道或 tty 设备)。
使用stdio
,取消缓冲输入流,将该缓冲区的大小设置为一个字节。
一次读取一个字节的效率很低,而且通常不需要。
可能需要它的情况是从不可查找的输入(如管道,所以f
如果它是常规文件,则不是您的)prog
读取并且需要在文件中的给定点停止读取,以便另一个进程可以恢复读取在那时候。
例如,在:
seq 10 | { grep -q 5; cat; }
Run Code Online (Sandbox Code Playgroud)
如果你想cat
输出第 6 到 10 行,那就是grep
停止读取文件之后的行(这里是一个管道,所以不可搜索)。
上面的命令不返回任何内容,因为一口气grep
读取了所有seq
的输出。
请注意,如果您已编写:
{ seq 5; sleep 1; seq 6 10; } | { grep -q 5; cat; }
Run Code Online (Sandbox Code Playgroud)
那会奏效的。grep
还请求一个大缓冲区,但由于当时只有前 5 行可用,因此grep
处理它们并在 5 日退出。换句话说,在缓冲区已满(或达到 eof)之前,它不会累积其输入以开始处理它(我所知道的唯一执行类似操作的命令是mawk
)。
使用某些命令,在 GNU 和 FreeBSD 系统上,您可以使用stdbuf -i
. 使用stdbuf -i0
(unbuffering) 将与stdbuf -i1
(读入大小为 1 的缓冲区)相同,并导致一次读取一个字节的输入。
它不适用于 GNU grep
,但它适用于 GNU sed
:
$ seq 10 | { sed -n /5/q; cat; }
$ seq 10 | { stdbuf -i0 sed -n /5/q; cat; }
6
7
8
9
10
Run Code Online (Sandbox Code Playgroud)
使用strace
,您可以看到read()
正在调整的s的大小:
$ seq 5 | { strace -e read sed -n /2/q; cat; }
[...]
read(0, "1\n2\n3\n4\n5\n", 4096) = 10
+++ exited with 0 +++
$ seq 5 | { strace -e read stdbuf -i0 sed -n /2/q; cat; }
[...]
read(0, "1", 1) = 1
read(0, "\n", 1) = 1
read(0, "2", 1) = 1
read(0, "\n", 1) = 1
+++ exited with 0 +++
3
4
5
$ seq 5 | { strace -e read stdbuf -i1 sed -n /2/q; cat; }
[...]
read(0, "1", 1) = 1
read(0, "\n", 1) = 1
read(0, "2", 1) = 1
read(0, "\n", 1) = 1
+++ exited with 0 +++
3
4
5
Run Code Online (Sandbox Code Playgroud)
您对问题的更改明确排除了执行此操作的方法。人们可以编辑程序来完成我们想要程序做的事情,或者使用一种工具来挂钩动态加载器和 C 运行时库的内部,以安排setvbuf
在程序启动时进行调用。
setvbuf
如果不允许使用该功能,则根本没有办法做到这一点。打电话setvbuf
是一个人需要做的事情。
归档时间: |
|
查看次数: |
2494 次 |
最近记录: |