如何正确计时在 C 中写入磁盘(即文件)的速度

How to correctly time speed of writing to a disk (i.e. file) in C

我有一个运行 Linux 系统的 Zynq SoC,我想计算我可以用 C 语言写入其 SD 卡的速度。

我已经尝试了 clock()clock_gettime(),对于后者,我做了以下操作:

#define BILLION 1000000000.0
#define BUFFER_SIZE 2097152
...

for (int i=0; i<100; i++) {
    memcpy(buf, channel->dma + offset, BUFFER_SIZE);
    
    /* Open file for output */
    FILE *f = fopen(path, "w");

    /* Start timer */
    clock_gettime(CLOCK_MONOTONIC, &start);

    /* Write data from cpu ram to sd card*/
    fwrite(buf, 1, BUFFER_SIZE, f);
    fclose(f);

    /* Stop timer and report result */
    clock_gettime(CLOCK_MONOTONIC, &end);
    elapsed_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / BILLION;
    printf("%lf seconds\n", elapsed_time);
}

对于 2097152 字节,我得到的时间约为 0.019 秒,我认为这是错误的,因为写入 SD 卡的速度被引用为 10 MB/s,不可能是 110 MB/s 我似乎得到了。当我将计时代码放在循环之外时,基本上,写下整个 100*BUFFER_SIZE 需要多长时间,我得到一个更合理的 18MB/s.

我的问题是,尝试为单个 fwrite 操作计时是否不正确? clock_gettime() 没有给我足够的 accuracy/precision 吗?我希望获得最准确的写入磁盘速度的值,因为它是系统设计中非常重要的参数,因此我得到的这种差异相当令人不安。

Linux 内核经常缓存对磁盘存储的读写访问。也就是说,它 returns 来自 write 调用并在后台进行实际写入。它透明地执行此操作,因此如果您读取同一个文件,在写入之后,您将获得您写入的结果,即使它们尚未传输并完全写入磁盘。

要强制完成写入,您可以调用 fsync 函数。它会阻塞,直到特定文件的所有文件 IO 完成。在你的情况下调用

#include <unistd.h>

...
fwrite(...);
fsync(fileno(f));

应该足够了。

编辑
正如评论中提到的@pmg,流级别也有缓冲。尽管它可能不是那么大的缓冲区,但您可以通过在 fsync.

之前调用 fflush() 来强制写入流缓冲区