linux内核将数据写入管道的位置

rka*_*ach 7 linux pipe

假设以下简单代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

main()
{
    int fd[2];                
    pipe(fd);
 // ...               
    write(fd, buf, VERY_BIG_NUMBER);
 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题:

  1. 有人可以解释写入数据的位置吗?
  2. 它是写入用户空间或内核空间中的某个缓冲区吗?
  3. 可以写入管道的最大长度是多少?
  4. 由于管道写入是阻塞操作,因此效率内核不会做任何事情并等待读者将数据直接传递给它吗?

Joh*_*ica 10

Linux上有一个通常为64KB的管道缓冲区.写入管道缓冲区.一旦它充满,write()系统调用就会阻塞,直到管道的另一端排出缓冲区.

摘自pipe(7)手册页:

管道的容量有限.如果管道已满,则write(2)将阻塞或失败,具体取决于是否O_NONBLOCK设置了标志(见下文).不同的实施方式对管道容量有不同的限制.应用程序不应该依赖于特定的容量:应该设计一个应用程序,以便读取过程一旦可用就会消耗数据,这样写入过程就不会被阻止.

在2.6.11之前的Linux版本中,管道的容量与系统页面大小相同(例如,i386上的4096字节).从Linux 2.6.11开始,管道容量为65536字节.

缓冲区位于内核空间中.管道通过虚拟pipefs文件系统实现.此文件系统的内核代码为每个pipe2()系统调用分配16个4KB页面,并且该缓冲区空间与为管道创建的inode相关联.read()write()系统调用将数据复制到用户空间和从用户空间复制数据.(来源)

如果它们低于4KB,写入管道是原子的.超过4KB的写入可能会导致页面错误,因此不再是原子的.这意味着如果写入大于4KB,则可以交叉来自不同进程的多个写入.

另请参见: 管道缓冲区有多大?