Linux上使用touch修改文件时间属性的限制
缘由
在Linux上我想多个进程对于同一个文件进行访问和修改,并且根据文件的最后修改时间来判断时间是否需要更新缓存中的文件,这样能够达到减少每次加载文件时间的损耗。
尝试的做法
每当我修改文件后,为了确保文件的最后修改时间的属性生效,会在执行一次touch
命令;然后在进程中需要读取文件时候,通过与缓存的上次加载此文件时候的最后修改时间对比,如果当前文件的最后读取时间新余缓存中的记录,则加载此文件,否则使用缓存中的文件。
最后修改时间属性能够获取的精度
通过获取属性能够获取,发现最大能够获取的时间是纳秒级别的,也就是逻辑上,如果不是在同一纳秒内修改文件则都能够识别出来才对。
失败的尝试
当我使用上述方式时候,发现有些时候多次快速读写,这种判断会失效,然后就开始分析。
可能原因的猜测
是否touch
命令修改时间的精度达不到呢?
实测代码分析(主要部分)
获取文件最后修改时间的代码
#include <sys/stat.h>
timespec TouchTimeUtils::GetLastModifiedTime(const std::string &filePath)
{
timespec currentTimeSpec;
currentTimeSpec.tv_sec = 0;
currentTimeSpec.tv_nsec = 0;
struct stat attrib;
if(0 == stat(filePath.c_str(), &attrib))
{
currentTimeSpec = attrib.st_mtim;
}
return currentTimeSpec;
}
touch文件的代码
void TouchTimeUtils::TouchFile(const std::string &filePath)
{
std::string cmd = "touch " + filePath;
system(cmd.c_str());
}
综合执行的代码
多次连续重复执行touch
,查看执行后文件最后修改时间的属性值。
std::string filePath = "/home/chaoyang/1.sh";
for (int i = 0; i < 1000; ++i)
{
TouchTimeUtils::TouchFile(filePath);
auto ts1 = TouchTimeUtils::GetLastModifiedTime(filePath);
TouchTimeUtils::TouchFile(filePath);
auto ts2 = TouchTimeUtils::GetLastModifiedTime(filePath);
TouchTimeUtils::TouchFile(filePath);
auto ts3 = TouchTimeUtils::GetLastModifiedTime(filePath);
std::cout << "index(" << i << "), " << "Time1(" << ts1.tv_sec << "," <<ts1.tv_nsec << "), "
<< "Time2(" << ts2.tv_sec << "," <<ts2.tv_nsec << "), "
<< "Time3(" << ts3.tv_sec << "," <<ts3.tv_nsec << ")" << std::endl;
}
结果分析
部分结果展示
如下的结果是使用debug编译执行的结果,仅仅展示其中的一部分。
····
index(671), Time1(1726277174,228191425), Time2(1726277174,232191461), Time3(1726277174,232191461)
index(672), Time1(1726277174,232191461), Time2(1726277174,236191494), Time3(1726277174,236191494)
index(673), Time1(1726277174,236191494), Time2(1726277174,240191528), Time3(1726277174,240191528)
index(674), Time1(1726277174,240191528), Time2(1726277174,244191561), Time3(1726277174,244191561)
index(675), Time1(1726277174,244191561), Time2(1726277174,248191594), Time3(1726277174,248191594)
index(676), Time1(1726277174,248191594), Time2(1726277174,252191629), Time3(1726277174,252191629)
index(677), Time1(1726277174,252191629), Time2(1726277174,252191629), Time3(1726277174,256191663)
index(678), Time1(1726277174,256191663), Time2(1726277174,256191663), Time3(1726277174,260191697)
index(679), Time1(1726277174,260191697), Time2(1726277174,260191697), Time3(1726277174,264191729)
index(680), Time1(1726277174,264191729), Time2(1726277174,264191729), Time3(1726277174,268191765)
index(681), Time1(1726277174,268191765), Time2(1726277174,268191765), Time3(1726277174,272191798)
index(682), Time1(1726277174,272191798), Time2(1726277174,272191798), Time3(1726277174,276191832)
index(683), Time1(1726277174,276191832), Time2(1726277174,276191832), Time3(1726277174,280191865)
index(684), Time1(1726277174,280191865), Time2(1726277174,280191865), Time3(1726277174,280191865)
index(685), Time1(1726277174,284191898), Time2(1726277174,284191898), Time3(1726277174,284191898)
index(686), Time1(1726277174,288191933), Time2(1726277174,288191933), Time3(1726277174,288191933)
index(687), Time1(1726277174,292191967), Time2(1726277174,292191967), Time3(1726277174,292191967)
index(688), Time1(1726277174,296192001), Time2(1726277174,296192001), Time3(1726277174,296192001)
index(689), Time1(1726277174,300192033), Time2(1726277174,300192033), Time3(1726277174,300192033)
index(690), Time1(1726277174,304192069), Time2(1726277174,304192069), Time3(1726277174,304192069)
index(691), Time1(1726277174,308192102), Time2(1726277174,308192102), Time3(1726277174,308192102)
index(692), Time1(1726277174,312192136), Time2(1726277174,312192136), Time3(1726277174,312192136)
index(693), Time1(1726277174,312192136), Time2(1726277174,316192169), Time3(1726277174,316192169)
index(694), Time1(1726277174,316192169), Time2(1726277174,320192202), Time3(1726277174,320192202)
index(695), Time1(1726277174,320192202), Time2(1726277174,324192237), Time3(1726277174,324192237)
index(696), Time1(1726277174,324192237), Time2(1726277174,328192271), Time3(1726277174,328192271)
index(697), Time1(1726277174,328192271), Time2(1726277174,332192305), Time3(1726277174,332192305)
index(698), Time1(1726277174,332192305), Time2(1726277174,336192337), Time3(1726277174,336192337)
···
在上面的执行时间中,最前面的第多少次测试,后面三组数字分别是执行的时间(秒、纳秒),发现很多的连续几次的时间是完全相同的。
结论
在Linux系统中,使用touch
来修改文件的最后修改数据属性,并不是每次都能在纳秒级别上修改到文件属性上,可能在极短时间内多次反映的修改时间会相同。