2

下面的 C 程序首先使用 clock_gettime() 获取时间,然后创建一个文件并读出其修改时间。至少在我的系统上,文件 mtime 是比 clock_gettime() 的结果更旧的时间戳。我的问题是如何解释这一点,是否有一个标准(例如 POSIX)来指定两者都必须按顺序排列?

/* Compile as C11 */
#define _POSIX_C_SOURCE 200809L

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    struct timespec buf_start; 

    int r= clock_gettime(CLOCK_REALTIME, &buf_start);
    if (r != 0) {
        perror("clock_gettime"); 
        exit(1); 
    }

    FILE *file= fopen("A", "w");
    if (file == NULL) {
        perror("A");
        exit(1); 
    }
    r= fputs("aaa\n", file); 
    if (r == EOF) {
        perror("A"); 
        exit(1);
    }
    r= fclose(file); 
    if (r != 0) {
        perror("A"); 
        exit(1); 
    }

    struct stat stat_file;

    r= stat("A", &stat_file);
    if (r != 0) {
        perror("A"); 
        exit(1); 
    }

    r= printf("%ld.%9ld\n%ld.%9ld\n",
          buf_start.tv_sec, buf_start.tv_nsec,
          stat_file.st_mtim.tv_sec, stat_file.st_mtim.tv_nsec);
    if (r < 0) {
        perror("printf"); 
        exit(1); 
    }

    exit(0);
}

在我的系统(Ubuntu 14.04)上,使用 gcc 4.8.4 和 ext4 文件系统,输出为:

1463778756.834469527
1463778756.832709123

即程序的启动时间在文件修改时间后报告为2 ms。

编辑:使用 CLOCK_REALTIME_COARSE,两个生成的时间戳完全相等,精确到纳秒。

编辑:clock_getres(CLOCK_REALTIME, ...) 返回的分辨率是一纳秒。

编辑:添加了文件系统信息。

4

1 回答 1

1

根据用户 Nos 的研究和提供的链接,这里是问题的答案:(免责声明:我是最初的提问者)

在 Linux 上,ext4 中的时间戳以纳秒精度保存,但时间戳本身被缓存。Linux 内核定期确定纳秒精度的时间(这是一项昂贵的操作)并将其保存在全局变量中。在该变量的下一次更新之前,写入磁盘(或其他一些数据结构)的所有时间戳都设置为此值,而不是当前时间。因此,ext4 文件系统中文件的时间戳有点太旧了。该错误大约为几毫秒。

另一方面,调用clock_gettime() 来获取当前时间会返回(计算成本高)高精度的当前时间。

就 POSIX 之类的标准而言,我找不到任何关于问题中给出的程序的声明。我认为这些问题将被视为任何“实时”行为的一部分,而不是通常操作系统界面的一部分。

实际上,可以使用 CLOCK_REALTIME_COARSE 来获得“文件系统兼容”的时间戳。然而,这是特定于 Linux 的,而且它的工作原理也是基于对 ext4 内部工作的了解,并且将来可能会在不公布的情况下发生变化。

对于 POSIX 标准,我希望有一个标志 CLOCK_FILESYSTEM 或类似的标志,可以保证像问题中给出的那样的程序按预期工作。这也将允许 clock_getres(CLOCK_FILESYSTEM) 返回该时钟的实际粒度。

于 2016-05-21T16:26:16.850 回答