linux下用utimes()修改文件atime最直接:先stat读取原atime/mtime,构造timeval数组(tv[0]设atime、tv[1]保持原mtime),再调用utimes();注意避免传null或tv_sec=0导致时间重置。

用 utimes() 修改文件访问时间(atime)最直接
Linux 下 touch -a 的核心就是更新 atime,C++ 没有跨平台标准接口,但 Linux/macOS 上 utimes() 是最轻量、最贴近系统行为的选择。它接受微秒级精度时间戳,比老式 utime() 更准,也避开了 utimensat() 需要 AT_FDCWD 和 flag 参数的繁琐。
常见错误是传入 NULL 时间指针——这会让系统用当前时间覆盖 mtime *和* atime,而你只想动 atime;或者误把 tv_sec 设为 0,导致时间被重置成 1970 年。
- 先用
stat()读出原文件的st_atime和st_mtime - 构造
timeval数组:tv[0]改 atime,tv[1]保持原 mtime 不变 - 调用
utimes("path", tv);返回 -1 且errno == ENOENT说明文件不存在
struct timeval tv[2];
struct stat st;
if (stat("foo.txt", &st) == 0) {
tv[0].tv_sec = st.st_atime; // 可改这里为新时间
tv[0].tv_usec = 0;
tv[1].tv_sec = st.st_mtime;
tv[1].tv_usec = 0;
utimes("foo.txt", tv);
}
想兼容 macOS?用 utimensat() 替代 utimes()
macOS 从 10.13 起已废弃 utimes(),链接时会警告,运行时也可能失败;utimensat() 是 POSIX.1-2008 标准,Linux 和新版 macOS 都支持,且能精确控制是否更新 atime/mtime/ctime。
关键区别在于:它用 timespec(纳秒级),不是 timeval(微秒级);第二个参数是 const struct timespec[2],顺序仍是 [atime, mtime];第三个参数必须传 AT_FDCWD,不能传文件描述符。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 若只想更新 atime,把
tv_nsec设为UTIME_OMIT表示跳过 mtime - 若两个都要设,两个
timespec都得填有效值,不能留空 - 注意头文件:
<sys></sys>和<fcntl.h></fcntl.h>缺一不可
为什么不用 futimens()?它不适用这个场景
futimens() 看起来更“现代”,但它操作的是已打开的文件描述符,而 touch 是路径操作——你得先 open() 再 futimens(),多一次系统调用,还容易因 O_RDONLY/O_WRONLY 模式影响后续行为。更麻烦的是:某些文件系统(如 ext4 默认挂载)启用了 relatime 或 noatime,即使调用成功,atime 也可能被内核忽略或延迟更新。
-
futimens()适合在已持有 fd 的上下文中顺带更新时间,比如日志写入后同步 atime - 单独为改 atime 去 open 文件,反而增加出错点:权限不足、路径被 symlink 中断、文件被删除等
- 实测中,
utimes()和utimensat()在noatime挂载下仍可强制写入(需 root 或chmod +a权限),futimens()则不一定
绕不开的内核限制:noatime 和 relatime 会影响结果
即使代码完全正确,执行后 ls -lu 看不到 atime 变化,大概率是文件系统挂载选项在起作用。这不是程序 bug,而是内核策略。
-
noatime:彻底禁用 atime 更新,所有用户态调用均被静默忽略(root 除外) -
relatime(默认):只在 atime 早于 mtime/ctime 时才更新,避免频繁磁盘写入 - 检查方式:
mount | grep "$(df . | tail -1 | awk '{print $1}')",看输出里有没有noatime或relatime - 临时绕过:
sudo mount -o remount,relatime /path/to/fs;但生产环境别乱改
真正难搞的不是怎么调系统调用,而是确认目标文件是否落在受控挂载点上——这点连 touch 命令本身都无能为力。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










