setbuf 只影响 stdio 调用,不影响系统调用?
setbuf only affects stdio calls, not system calls?
我试图更深入地了解缓冲在 C
和 stdio
中的工作原理,我发现了一些我觉得很有趣的东西。我阅读了 this 文章,但我想确认我的理解是否正确。
当我使用 fgets
时,将输入缓冲设置为 3 个字节 (stdbuf -i3
) 并检查 strace
,我看到读取以 3 个字符为一组进行,这我预计:
read(0, "hel", 3) = 3
read(0, "lo\n", 3) = 3
...
如果我仍然使用 stdbuf
但这次我改为执行 read(2)
系统调用,它会立即读取全部内容(最多 4096 字节):
read(0, "hello\nworld!\n\n", 4096) = 14
所以它忽略了 stdbuf
调用。
这让我彻底重新思考 stdio
缓冲。 stdio
本质上是否维护自己的缓冲区,而 stdbuf -i3
是说从内核中的主管道缓冲区一次读入该缓冲区 3 个字节?我认为做 stdbuf -i0
会使管道的容量无法容纳超过一个字节(即 write(2)
调用会在进程发送 stdout
的 1 个字节后阻塞进程的无缓冲 stdin
).
那么说在实际管道缓冲区之上有 2 个缓冲区进一步缓冲 stdout
和 stdin
是否正确?而 setbuf
只控制这两个缓冲区,而不是修改内核管道缓冲区的任何属性。因此,将 stdin
设置为 n
字节缓冲区意味着它将在返回内核以执行 read
系统调用之前保留 n
字节。
缓冲仅存在于 libc 中,即您从 stdio 调用的函数。系统调用接口没有缓冲。如果您进行系统调用(使用例如 read
或 write
),通常 libc 包装器在调用内核之前会做很少的事情。
command
must start with the name of a program that ... uses the ISO C FILE streams for input/output (note the programs dd
and cat
don’t do that),
这是因为stdbuf
works通过pre-loading一个库进入目标程序从而改变了缓冲模式(在它的libc中)。直接进行系统调用的程序不受影响。
stdbuf
不会改变内核中管道缓冲区的大小。此缓冲区与 libc 提供的缓冲无关。
Does stdio maintain its own buffer essentially, and stdbuf -i3 is saying to read into that buffer 3 bytes at a time from the main pipe buffer in the kernel?
是的。 Libc 为 stdio.h FILE
流提供缓冲区。
我试图更深入地了解缓冲在 C
和 stdio
中的工作原理,我发现了一些我觉得很有趣的东西。我阅读了 this 文章,但我想确认我的理解是否正确。
当我使用 fgets
时,将输入缓冲设置为 3 个字节 (stdbuf -i3
) 并检查 strace
,我看到读取以 3 个字符为一组进行,这我预计:
read(0, "hel", 3) = 3
read(0, "lo\n", 3) = 3
...
如果我仍然使用 stdbuf
但这次我改为执行 read(2)
系统调用,它会立即读取全部内容(最多 4096 字节):
read(0, "hello\nworld!\n\n", 4096) = 14
所以它忽略了 stdbuf
调用。
这让我彻底重新思考 stdio
缓冲。 stdio
本质上是否维护自己的缓冲区,而 stdbuf -i3
是说从内核中的主管道缓冲区一次读入该缓冲区 3 个字节?我认为做 stdbuf -i0
会使管道的容量无法容纳超过一个字节(即 write(2)
调用会在进程发送 stdout
的 1 个字节后阻塞进程的无缓冲 stdin
).
那么说在实际管道缓冲区之上有 2 个缓冲区进一步缓冲 stdout
和 stdin
是否正确?而 setbuf
只控制这两个缓冲区,而不是修改内核管道缓冲区的任何属性。因此,将 stdin
设置为 n
字节缓冲区意味着它将在返回内核以执行 read
系统调用之前保留 n
字节。
缓冲仅存在于 libc 中,即您从 stdio 调用的函数。系统调用接口没有缓冲。如果您进行系统调用(使用例如 read
或 write
),通常 libc 包装器在调用内核之前会做很少的事情。
command
must start with the name of a program that ... uses the ISO C FILE streams for input/output (note the programsdd
andcat
don’t do that),
这是因为stdbuf
works通过pre-loading一个库进入目标程序从而改变了缓冲模式(在它的libc中)。直接进行系统调用的程序不受影响。
stdbuf
不会改变内核中管道缓冲区的大小。此缓冲区与 libc 提供的缓冲无关。
Does stdio maintain its own buffer essentially, and stdbuf -i3 is saying to read into that buffer 3 bytes at a time from the main pipe buffer in the kernel?
是的。 Libc 为 stdio.h FILE
流提供缓冲区。