假设有以下简单代码:
#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()
系统调用会阻塞,直到管道的另一端耗尽缓冲区。
摘自管道(7) 手册页 http://linux.die.net/man/7/pipe:
管道的容量是有限的。如果管道已满,则 write(2) 将阻塞或失败,具体取决于管道是否已满O_NONBLOCK
标志已设置(见下文)。不同的实现对管道容量有不同的限制。应用程序不应依赖于特定的容量:应用程序的设计应使读取过程在数据可用时立即使用数据,以便写入过程不会保持阻塞状态。
在 2.6.11 之前的 Linux 版本中,管道的容量与系统页面大小相同(例如,i386 上为 4096 字节)。从Linux 2.6.11开始,管道容量为65536字节。
缓冲区位于内核空间中。管道是通过虚拟 pipelinefs 文件系统实现的。该文件系统的内核代码为每个文件分配 16 个 4KB 页面pipe2()
系统调用,并且该缓冲区空间与为管道创建的索引节点相关联。read()
and write()
系统调用将数据复制到用户空间或从用户空间复制数据。 (Source http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos)
如果写入管道的大小小于 4KB,则它们是原子的。超过 4KB 的写入可能会导致页面错误,因此不再是原子的。这意味着,如果写入大于 4KB,则来自不同进程的多个写入可能会交错。
也可以看看: 管道缓冲区有多大? https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)