Linuxのファイルシステム時間が常にシステム時間より数ミリ秒遅いのはなぜですか?

Linuxのファイルシステム時間が常にシステム時間より数ミリ秒遅いのはなぜですか?

Linuxでは、ファイルシステム時間が常にシステム時間より数ミリ秒遅れているように見えるため、非常に狭い時間範囲(ミリ秒)内で特定の時間の前後にファイルが変更されたことを確認しようとすると、不一致が発生する可能性があります。

ナノ秒の解像度をサポートするファイルシステムを備えたLinuxシステム(私は256バイトのinodeとZFSでext4を使ってみました)で次のことをしようとしました:

date +%H:%M:%S.%N; echo "hello" > test1; stat -c %y test1 | cut -d" " -f 2

2番目の出力値(ファイル修正時間)は、常に最初の出力値(システム時間)より数ミリ秒遅れます。たとえば、次のようになります。

17:26:42.400823099
17:26:42.395348462

反対方向でなければなりませんが、ファイルがtest1変更されたため後ろにdateコマンドを呼び出します。

Pythonでも同じ結果が得られます。

import os, time

def test():
    print(time.time())
    with open("test1", "w") as f:
        f.write("hello")
        print(os.stat("test1").st_mtime)

test()
1698255477.3125281
1698255477.3070245

なぜこれが起こるのですか?これを防ぎ、システム時間をファイルシステム時間と一致させる方法はありますか?これまで私が見つけた唯一の回避策は、ダミーの一時ファイルを次のように作成し、修正時間を取得してファイルシステム「時間」(実際に何を意味するのか)を取得することです。

def get_filesystem_time():
    """
    get the current filesystem time by creating a temporary file and getting
    its modification time.
    """
    with tempfile.NamedTemporaryFile() as f:
        return os.stat(f.name).st_mtime

しかし、よりクリーンな解決策があるかどうか疑問に思います。

ベストアンサー1

ファイルタイムスタンプに使用される時間は経過した最後のタイマーであり、これは常にわずかに過去です。このcurrent_time機能はinode.c着信電話ktime_get_coarse_real_ts64:

/**
 * current_time - Return FS time
 * @inode: inode.
 *
 * Return the current time truncated to the time granularity supported by
 * the fs.
 *
 * Note that inode and inode->sb cannot be NULL.
 * Otherwise, the function warns and returns time without truncation.
 */
struct timespec64 current_time(struct inode *inode)
{
    struct timespec64 now;

    ktime_get_coarse_real_ts64(&now);

    if (unlikely(!inode->i_sb)) {
        WARN(1, "current_time() called with uninitialized super_block in the inode");
        return now;
    }

    return timestamp_truncate(now, inode);
}

後者は次の一部です以下の関数群を記録してください。:

これは、おおよそのバージョンよりも高速ですが、ユーザースペースに対応し、ユーザーCLOCK_MONOTONIC_COARSEスペースCLOCK_REALTIME_COARSEで使用できない同等のブートタイム/ tai / rawタイムベースによっては精度が低下します。

ここで返された時間は最後のタイマーティックに対応し、おそらく過去10ミリ秒(CONFIG_HZ = 100の場合)であり、「jiffies」変数を読み取るのと同じです。これらの[関数]は高速パスで呼び出された場合にのみ有用であり、まだ秒よりも良い精度を期待しますが、例えばinodeタイムスタンプの場合は「jiffies」を簡単に使用することはできません。ハードウェアクロックアクセスをスキップすると、信頼できるサイクルカウンタを持つほとんどの最新システムでは約100 CPUサイクルが節約されますが、外部クロックソースを持つ古いハードウェアでは最大数マイクロ秒まで節約できます。

inodeタイムスタンプの具体的な言及を参照してください。

カーネルを修正する以外に、これを完全に避ける方法はありません。増やすことで影響を減らすことができますCONFIG_HZ最近これを改善しようという提案がありました。、どちらまだ研究中

おすすめ記事