Linux 中的管道会丢失数据吗?

发布于 2024-08-29 23:29:51 字数 22 浏览 5 评论 0原文

它可以包含的数据量是否有上限?

And is there an upper limit on how much data it can contain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无所谓啦 2024-09-05 23:29:51

除非机器崩溃,否则不会丢失数据。然而,很容易误用它并认为您正在丢失数据,要么是因为写入未能写入您请求的所有数据并且您没有检查返回值,要么是因为读取时出现了错误。

它可以容纳的最大数据量取决于系统 - 如果您尝试写入超过该数据,您将得到一个简短的写入,或者写入器将阻塞,直到有可用空间为止。 pipe(7) 手册页包含许多有关管道的有用信息,包括(至少在 Linux 上)缓冲区有多大。 Linux 有 4K 或 64K 的缓冲区,具体取决于版本。

编辑

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

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

Barring a machine crash, no it can't lose data. It's easy to misuse it and think you're losing data however, either because a write failed to write all the data you requested and you didn't check the return value or you did something wrong with the read.

The maximum amount of data it can hold is system dependent -- if you try to write more than that, you'll either get a short write or the writer will block until space is available. The pipe(7) man page contains lots of useful info about pipes, including (on Linux at least) how big the buffer is. Linux has buffers of 4K or 64K depending on version.

edit

Tim mentions SIGPIPE, which is also a potential issue that can seem to lose data. If the reader closes the pipe before reading everything in it, the unread data will be thrown away and the writer will get a SIGPIPE signal when they write more or close the pipe, indicating that this has occurred. If they block or ignore the SIGPIPE, they'll get an EPIPE error. This covers the situation Paul mentioned.

PIPE_BUF is a constant that tells you the limit of atomic writes to the buffer. Any write this size or smaller will either succeed completely or block until it can succeed completely (or give EWOULDBLOCK/EAGAIN if the pipe is in non-blocking mode). It has no relation to the actual size of the kernel's pipe buffer, though obviously the buffer must be at least PIPE_BUF in size to meet the atomicity guarentee.

困倦 2024-09-05 23:29:51

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

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

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

检测此问题的非标准方法是编写者定义超时并调用 FIONREAD ioctl 来确定管道缓冲区中剩余的字节数。

Data can be lost in a pipe when the following happens:

  1. A process (the writer) writes n bytes of data to the pipe, where n≤PIPE_BUF. This write is guaranteed to be atomic and will never block.
  2. A process (the reader) reads only m<n bytes of data and exits.
  3. The writer doesn’t attempt to write to the pipe again.

As a result, the kernel pipe buffer will contain n-m bytes which will be lost when all handles to the pipe have been closed. The writer will not see SIGPIPE or EPIPE since it never attempts to write to the pipe again. Since the writer won’t ever learn that the pipe contains leftover data that will simply disappear, one can consider this data lost.

A non-standard way of detecting this would be for the writer to define a timeout and call the FIONREAD ioctl to determine the number of bytes left in the pipe buffer.

猛虎独行 2024-09-05 23:29:51

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

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

If you are referring to using the | operator in the shell then no, it will not lose data. It merely connects the app on the left side's standard output stream to the app on the right side's standard input stream. If you are piping data between apps and aren't getting the results you expect, try using > to redirect standard output from the first app to a file and then use < to use that file as standard input for the second app. That way, you can inspect the file amd make sure the data is being sent in the format you expect.

If you mean a pipe created by the pipe function then the answer is still no. According to this man page, writing to a full pipe will block until enough data has been read to make room for the write data. It also states that the size of a pipe is 4KB in Linux pre-2.6.11, and is 64kB on 2.6.11 and later.

音盲 2024-09-05 23:29:51

您的管道不会丢失数据。如果您的应用程序丢失了数据,请尝试使用 gdb 进行调试。
需要注意以下几点:
1)您的缓冲区是否足够大以容纳您正在读取的所有数据?
2) 检查管道上 read() 的返回码是否有错误。
3)您确定将所有数据写入管道吗?
4)您的写/读操作是否被信号中断?即:SIGPIPE?

Your pipe isn't losing data. If you're losing data in your application, try debugging it with gdb.
A couple of things to look for:
1) Is your buffer large enough to hold all the data that you're reading?
2) Check the return codes from your read() on the pipe for errors.
3) Are you sure you're writing all of the data to the pipe?
4) Is your write/read operation getting interrupted by a signal? ie: SIGPIPE?

十秒萌定你 2024-09-05 23:29:51

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

The reason you will not lose data is that when the buffer associated with the pipe fills up a call to write will block until the reader has emptied the buffer enough for the operation to complete. (You can do non-blocking writes as well, but then you are responsible for making sure you complete any writes that would have blocked.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文