linux - linux内核在哪里保存写入管道的数据

标签 linux pipe

假设有以下简单代码:

#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. 既然管道写是阻塞操作,内核为了效率岂不是什么都不做,等待读取器直接将数据传递给它?

最佳答案

有一个管道缓冲区,在 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,则来自不同进程的多个写入可以交错。

另请参阅: How big is the pipe buffer?

关于linux - linux内核在哪里保存写入管道的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33151457/

相关文章:

c++ - 如何使这个管道在 C++ 中工作?

android - 将 Linux 更改 merge 到 Android 内核项目中

linux - 使用管道时如何在没有警告的情况下使用 zcat

linux - sed 读取没有换行的单行

shell - 使用 golang 从命令行读取输入到 shell 脚本 exec

具有大对象的 Python 多处理管道将挂起

Linux系统 ("top -p pid") 程序中的命令

linux - 用于远程访问的 ssh-keygen 不起作用

php - 从 STDIN 逐行读取

c - 我应该如何使用 FIFO 等待子进程的输入