假设有以下简单代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
main()
{
int fd[2];
pipe(fd);
// ...
write(fd, buf, VERY_BIG_NUMBER);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
现在我的问题:
- 有人可以解释写入将把数据放在哪里吗?
- 它是否写入了位于用户空间或内核空间的某个缓冲区?
- 可以写入管道的最大长度是多少?
- 既然管道写是阻塞操作,内核为了效率岂不是什么都不做,等待读取器直接将数据传递给它?
最佳答案
有一个管道缓冲区,在 Linux 上通常为 64KB。写入管道缓冲区。一旦缓冲区已满,write()
系统调用就会阻塞,直到管道的另一端耗尽缓冲区。
摘自 pipe(7) man page :
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the
O_NONBLOCK
flag is set (see below). Different implementations have different limits for the pipe capacity. Applications should not rely on a particular capacity: an application should be designed so that a reading process consumes data as soon as it is available, so that a writing process does not remain blocked.In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11, the pipe capacity is 65536 bytes.
缓冲区在内核空间。管道是通过虚拟 pipefs 文件系统实现的。该文件系统的内核代码为每个 pipe2()
系统调用分配 16 个 4KB 页面,并且该缓冲区空间与为管道创建的 inode 相关联。 read()
和 write()
系统调用将数据复制到用户空间和从用户空间中复制出来。 ( Source )
如果写入管道小于 4KB,则写入是原子的。超过 4KB 的写入可能会导致页面错误,因此不再是原子的。这意味着如果写入大于 4KB,则来自不同进程的多个写入可以交错。
关于linux - linux内核在哪里保存写入管道的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33151457/