Linux中的pipe道是否会丢失数据?

有多less数据可以包含上限?

除非机器崩溃,否则不会丢失数据。 这很容易误用它,并认为你正在丢失数据,或者是因为写入没有写出你所请求的所有数据,而你没有检查返回值,或者你在读取时做了错误。

它可以容纳的最大数据量取决于系统 – 如果你试图写更多的数据,你可能会得到一个简短的写或写作者将阻塞,直到空间可用。 pipe(7)手册页包含许多关于管道的有用信息,包括(至少在Linux上)缓冲区有多大。 Linux根据版本具有4K或64K的缓冲区。

编辑

Tim提到SIGPIPE,这也是一个潜在的问题,可能会丢失数据。 如果读取器在读取所有内容之前关闭了管道,则未读取的数据将被丢弃,写入更多或关闭管道时,写入器将收到SIGPIPE信号,表明发生了这种情况。 如果他们阻止或忽略SIGPIPE,他们会得到一个EPIPE错误。 这涵盖了保罗提到的情况。

PIPE_BUF是一个常数,告诉你原子写入缓冲区的限制。 任何写入这个大小或更小的将会完全成功或阻塞直到它可以完全成功(或者如果管道处于非阻塞模式则给出EWOULDBLOCK / EAGAIN)。 它和内核的管道缓冲区的实际大小没有任何关系,但显然缓冲区的大小必须至少为PIPE_BUF才能满足原子性保证。

发生以下情况时,数据可能会丢失在管道中:

  1. 一个进程(作者)写n个字节的数据到管道,其中n≤PIPE_BUF。 这写保证是原子,永远不会阻止。
  2. 一个进程(读者)只读取m <n个字节的数据并退出。
  3. 作者不会再次尝试写入管道。

因此,内核管道缓冲区将包含nm字节,当管道的所有句柄都被关闭时将会丢失。 作者将不会看到SIGPIPEEPIPE因为它永远不会再次尝试写入管道。 由于作者将不会知道管道中包含的残余数据将会消失,所以可以认为这些数据丢失了。

检测这种情况的非标准方法是编写者定义超时并调用FIONREAD ioctl来确定管道缓冲区中留下的字节数。

如果您指的是使用| 在shell中运算符不行,不会丢失数据。 它只是将左侧标准输出流上的应用程序连接到右侧标准输入流上的应用程序。 如果您在应用程序之间传输数据,但没有得到您期望的结果,请尝试使用>将第一个应用程序的标准输出重定向到一个文件,然后使用<将该文件用作第二个应用程序的标准输入。 这样,你可以检查文件和确保数据是以你期望的格式发送。

如果你的意思是由pipe功能创建的pipe那么答案仍然是否定的。 根据这个手册页 ,写入一个完整的管道将被阻塞,直到读取了足够的数据以为写入数据腾出空间。 它还指出在Linux 2.6.11之前,一个管道的大小是4KB,2.6.11及更高版本是64kB。

你的管道不会丢失数据。 如果你的应用程序丢失数据,请尝试使用gdb进行调试。 一些事情要寻找:
1)您的缓冲区是否足够容纳您正在阅读的所有数据?
2)检查管道上read()的返回代码是否有错误。
3)你确定你正在把所有的数据写入管道吗?
4)您的写/读操作是否被信号中断? 即:SIGPIPE?

不会丢失数据的原因是,当与管道相关联的缓冲区填满了write调用时,将会阻塞,直到读取器清空缓冲区足以完成操作。 (您也可以进行非阻塞式写入,但是您有责任确保您完成任何将被阻止的写入操作。)