POSIX 中的 fopen 与 open(C 语言)

Dan*_*ira 2 c io fopen posix

这个问题问完之后,一个疑问就来了:

一旦fopen()比open()更快(至少对于顺序写入/就绪操作),前者是一个库,后者是一个系统调用,那么fopen()在 POSIX 兼容操作系统中执行什么系统调用?

zwo*_*wol 5

它调用open.

fopen本身并不比open;快 不可能,这open还需要一些额外的工作。链接问题中描述的性能优势来自FILE对象在其整个生命周期中完成的“缓冲”。实际的优化是调用write原语的次数更少,每次提供更多的数据。

下面用一个简单的方法来演示效果:编译这个程序。

#define _XOPEN_SOURCE 700
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    if (argc != 3) return 1;
    long count = atol(argv[1]);
    long chunk = atol(argv[2]);
    if (count < 1 || chunk < 0) return 1;

    FILE *sink = fopen("/dev/null", "wb");
    if (!sink) return 1;

    if (chunk) {
        char *buf = malloc(chunk);
        if (!buf) return 1;
        if (setvbuf(sink, buf, _IOFBF, chunk)) return 1;
    } else {
        if (setvbuf(sink, 0, _IONBF, 0)) return 1;
    }

    while (count--) putc_unlocked('.', sink);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它需要两个参数:按顺序写入的字节总数和输出缓冲区的大小。使用不同的参数值运行它并对其性能进行计时;你应该看到,例如

./a.out $((1024*1024*128)) 1
Run Code Online (Sandbox Code Playgroud)

./a.out $((1024*1024*128)) 8192
Run Code Online (Sandbox Code Playgroud)

第一个数字需要非常大才能测量差异。一旦你玩了一段时间,运行

strace ./a.out 50 1
Run Code Online (Sandbox Code Playgroud)

strace ./a.out 50 50
Run Code Online (Sandbox Code Playgroud)

了解系统调用级别发生的情况的差异。(如果您使用的是 Linux 以外的操作系统,请替换strace为该操作系统的等效命令。)

  • 此外,使用“fopen()”以外的 stdio 函数“本质上”并不比使用 POSIX I/O 函数更快。例如,人们可以使用后者执行自己的缓冲,甚至可能更好地调整以适应当前的用例。但 stdio 函数确实隐藏了大量的低级细节,而且还提供了这些细节的经过良好测试的实现。 (2认同)