直接从FILE缓冲区读取

时间:2014-02-03 12:09:54

标签: c linux glibc

我的应用程序的核心大致如下:

size_t bufsize;
char*  buf1;
size_t r1; 
FILE* f1=fopen("/path/to/file","rb");
...
do{
  r1=fread(buf1, 1, bufsize, f1);
  processChunk(buf1,r1);
} while (!feof(f1));
...

(实际上,我有多个FILE*和多个bufN。)现在,我听说FILE已准备好管理缓冲区(称为“流缓冲区”)所有这些,这种行为似乎是可以调整的:https://www.gnu.org/software/libc/manual/html_mono/libc.html#Controlling-Buffering

如何重构上面的代码以放弃buf1缓冲区并使用f1的内部流缓冲区(将其设置为bufsize)?

2 个答案:

答案 0 :(得分:1)

如果您不想要不透明缓冲的I / O,请不要使用FILE *。使用较低级别的API,您可以自己管理所有应用程序端缓冲,例如普通POSIX open()read()

答案 1 :(得分:0)

所以我已经阅读了一些C标准并运行了一些基准测试,这是我的发现:

1)按照上面的例子进行操作确实涉及不必要的内存中复制,这使得基于上述示例的简单cmp程序的用户时间增加了大约两倍。然而,对于大多数IO重量级的程序来说,用户时间是微不足道的,除非文件的来源非常快。 但是,在内存文件源(Linux上为/dev/shm)上,关闭FILE缓冲(setvbuf(f1, NULL, _IONBF, 0);)确实会产生一个很好且持续的速度提升约10-15%使用接近BUFSIZ的buffsizes时的机器(再次,根据上面的代码片段测量IO重cmp实用程序,我已经提到过,我在2个相同的700MB文件上测试了100次)。

2)虽然有一个用于设置FILE缓冲区的API,但我没有找到任何用于阅读它的标准化API,所以我将坚持使用真实且经过测试的方法,但是关闭FILE缓冲区(setvbuf(f1, NULL, _IONBF, 0);

(但我想我可以通过将自己的缓冲区设置为带有_IONBF模式选项的FILE流缓冲区来解决我的问题(=关闭缓冲),然后我可以通过FILE结构中的一些非标准化指针来访问它。 )