【问题标题】:fopen vs open (in C) in POSIXPOSIX 中的 fopen 与 open(在 C 中)
【发布时间】:2021-12-02 20:23:09
【问题描述】:

question之后,出现了一个疑问:

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

【问题讨论】:

  • 这取决于实现,但通常fopen 最终会调用open
  • 我查看了 glibc,它似乎可能根据用例使用mmap
  • @Lundin 但是要调用mmap,它必须先调用open(可能open_memstream 除外,但这是完全不同的情况)
  • @zwol 我只看了一眼代码,但只读等有不同的用例。
  • fopen() 肯定不会比open() 快(可能要慢得多,因为它必须设置缓冲)但它可能会导致稍后的 I/O 更快。

标签: c io posix fopen


【解决方案1】:

它调用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;
}

它有两个参数:要写入的字节总数和输出缓冲区的大小,按顺序排列。使用不同的参数值和时间运行它;你应该看到,例如

./a.out $((1024*1024*128)) 1

慢很多
./a.out $((1024*1024*128)) 8192

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

strace ./a.out 50 1

strace ./a.out 50 50

了解系统调用级别的不同之处。 (如果您使用的是 Linux 以外的操作系统,请将 strace 替换为该操作系统的等效命令。)

【讨论】:

  • 此外,使用 fopen() 以外的 stdio 函数并不固有地比使用 POSIX I/O 函数快。例如,可以使用后者执行自己的缓冲,甚至可能根据手头的用例更好地调整它。但 stdio 函数确实隐藏了大量的低级细节,而且提供了经过良好测试的这些细节的实现。
  • 在我的系统中,1 分 20,0762 秒对 0.762 秒。大约慢了 106 倍!
猜你喜欢
  • 2010-12-12
  • 2016-02-20
  • 2012-09-19
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 2020-09-28
相关资源
最近更新 更多