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 ミリ秒後に報告されます。

編集: CLOCK_REALTIME_COARSE を使用すると、結果として得られる 2 つのタイムスタンプは、ナノ秒まで正確に等しくなります。

編集: clock_getres(CLOCK_REALTIME, ...) によって返される解像度は 1 ナノ秒です。

編集: ファイルシステム情報を追加しました。

4

1 に答える 1

1

ユーザー番号による調査と提供されたリンクに基づいて、質問に対する回答を以下に示します: (免責事項: 私は元の質問者です)

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 に答える