时钟偏差与clock_gettime和struct stat.mtim

时间:2016-05-20 21:17:17

标签: c filesystems posix clock real-time-clock

以下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,...)返回的分辨率是1纳秒。

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

1 个答案:

答案 0 :(得分:1)

根据用户编号和提供的链接进行的研究,以下是对问题的回答:(免责声明:我是原问题提问者)

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

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

就像POSIX这样的标准来说,我找不到任何关于程序的陈述,就像问题中给出的那样。我认为这些问题将被视为任何&#34;实时&#34;行为,而不是通常的操作系统界面的一部分。

实际上,可以使用CLOCK_REALTIME_COARSE来获得&#34;文件系统兼容&#34;时间戳。然而,这是特定于Linux的,并且它工作的事实也基于有关ext4的内部工作的知识,并且可能在未来未经通知的情况下改变。

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