ajw*_*ood 5 unix perl timestamp ext4
我看到Perl Time::HiRes模块报告的时间戳有些奇怪的行为.
我有一个获得三个时间戳的脚本:
Time::HiRes::timeTime::HiRes::statTime::HiRes::time我希望订购时间戳1 < 2 < 3,但情况并非总是如此; 通常(但不总是),stat在2.中报告的时间是在 1 之前的时间戳之前.
我在Ext4文件系统上.这是一个实验:
use Time::HiRes qw/ time stat /;
while( 1 ){
# t0
my $t0 = time;
# Create a file
my $f = '/tmp/dummy.test';
open(my $fh, '>', $f) || die;
print $fh "hi\n";
close($fh) || die;
# FS: file modification time, according to the filestystem
my $fs = (stat($f))[9];
# t1
my $t1 = time;
## Report how the timestamps relate to each other
# A. All good
if( $t0 < $fs && $fs < $t1 ){
print "$t1,0\n";
}
# B. FS before t0
elsif( $t0 > $fs && $fs < $t1 ){
print "$t1,1\n";
}
# C. FS after t1
elsif( $t0 < $fs && $fs > $t1 ){
print "$t1,2\n";
}
# D. this should never happen (t0 and t1 probably can't flip)
elsif( $t0 > $fs && $fs > $t1 ){
print "$t1,3\n";
}
}
Run Code Online (Sandbox Code Playgroud)
以下是让上述循环运行几秒钟的结果.底部的蓝点是"正确"行为的事件.通常情况下,我得到条件B,其中修改时间stat是在第一个时间戳之前.
有什么可以解释这种行为?
更新:这是第2000次迭代的时间戳滞后图:
这可能是因为这里的doc中提到的两个时间戳的精度不同:
作为stat或lstat,但访问/修改/更改文件时间戳以亚秒级分辨率,如果操作系统和文件系统都支持这样的时间戳.要覆盖标准stat():
Run Code Online (Sandbox Code Playgroud)use Time::HiRes qw(stat);测试&Time :: HiRes :: d_hires_stat的值以确定操作系统是否支持亚秒文件时间戳:大于零的值表示是.遗憾的是,没有简单的方法可以确定文件系统是否支持这样的时间戳.UNIX文件系统经常这样做; NTFS确实; FAT没有(FAT时间戳粒度为2秒).
&Time :: HiRes :: d_hires_stat的零返回值意味着Time :: HiRes :: stat是CORE :: stat()的无操作直通(对于lstat也是如此),因此时间戳将保持整数.如果文件系统不执行亚秒级时间戳,即使&Time :: HiRes :: d_hires_stat非零,也会发生同样的情况.
在任何情况下都不要指望纳秒分辨率,甚至是微秒分辨率.另请注意,修改/访问时间戳可能具有不同的分辨率,并且无需同步,例如,如果操作是
Run Code Online (Sandbox Code Playgroud)write stat # t1 read stat # t2来自t2的访问时间标记不必大于来自t1的修改时间标记:它可以等于或小于.