8

我正在使用函数调用fwrite()将数据写入 Linux 上的管道。

早些时候,fwrite()被反复调用小块数据(平均 20 个字节)并且缓冲留给fwrite(). 对进程的 strace 显示一次写入了 4096 字节的数据。

原来,这个编写过程是我程序的瓶颈。所以我决定将代码中的数据缓冲成 64KB 的块,然后使用fwrite(). 我曾经setvbuf()将 FILE* 指针设置为“无缓冲”。

性能提升并不像我预期的那么显着。

更重要的是,strace输出显示数据仍一次写入 4096 字节。有人可以向我解释这种行为吗?如果我fwrite()用 64KB 的数据调用,为什么一次只写入 4096 字节?

fwrite()有没有使用 FILE* 指针将数据写入管道的替代方法?

4

2 回答 2

8

4096 来自作为管道基础的 Linux 机器。它发生在两个地方。一是管道的容量。在旧版本的 Linux 上,容量是一个系统页面,在 32 位 i386 机器上是 4096 字节。(在更现代的 Linux 版本上,容量为 64K。)

您将遇到 4096 字节问题的另一个地方是定义的常量PIPE_BUF,即保证以原子方式处理的字节数。在 Linux 上,这是 4096 字节。此限制的含义取决于您是否将管道设置为阻塞或非阻塞。man -S7 pipe为所有血淋淋的细节做一个。

如果您尝试高速交换大量数据,您可能需要重新考虑使用管道。您在 Linux 机器上,因此可以选择共享内存。您可以使用管道作为信号机制发送相对少量的数据。

于 2012-04-25T07:57:58.623 回答
4

如果你想改变缓冲行为,你必须在fopen(或任何 I/O 之前,对于标准文件句柄stdin, stdout, stderr)之后立即进行。您也不想禁用缓冲并尝试自己管理缓冲区;相反,请指定您的 64K 缓冲区,setvbuf以便它可以正确使用。

如果您真的想手动管理缓冲,请不要使用stdio; 使用较低级别openwrite、 和close调用。

于 2012-04-25T07:33:19.323 回答