2015-10-15 72 views
3

假设以下简单的代码数据:哪里linux内核保持写入管

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

main() 
{ 
    int fd[2];     
    pipe(fd); 
// ...    
    write(fd, buf, VERY_BIG_NUMBER); 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
} 

现在我的问题:

  1. 有人能解释其中写将会把这些数据?
  2. 是否写入位于用户空间或内核空间的某个缓冲区?
  3. 什么是可以写入管道的最大长度?
  4. 由于管道写入操作是阻塞操作,内核效率是不是没有任何作用,并等待读者直接将数据传递给它?
+1

[人7管(http://man7.org/linux/man-pages/man7/pipe.7.html) – rici

+0

@rici我只是咨询人2,感谢您指出正确的页面。 – redobot

回答

6

在Linux上有一个管道缓冲区,通常为64KB。写入管道缓冲区。一旦它满了,系统调用将会阻塞,直到管道的另一端排出缓冲区。从pipe(7) man page

摘录:

的管具有有限的容量。如果管道已满,则写入(2)将会阻塞或失败,具体取决于O_NONBLOCK标志是否已设置(请参见下文)。不同的实现对管道容量有不同的限制。应用程序不应该依赖于特定的容量:应该设计应用程序,以便读取过程在可用时立即使用数据,以便写入过程不会被阻止。

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

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

写入管道是原子,如果他们在4KB以下。超过4KB的写入可能会导致页面错误,因此不再是原子性的。这意味着如果写入大于4KB,则可以将来自不同进程的多次写入交错。

参见:How big is the pipe buffer?