access函数用于检查文件路径权限,参数R_OK/W_OK/X_OK/F_OK分别表示读、写、执行和存在性检查;但存在竞态风险,应优先直接open并处理errno。

access 函数怎么用,参数 R_OK/W_OK/X_OK 是啥
access 是 POSIX 标准的系统调用(头文件 ),C++ 中可直接调用。它不依赖 C++ 标准库,而是通过内核检查当前进程对指定路径的权限。
关键点:它检查的是「真实用户 ID(real UID)」的权限,不是有效 UID(比如 setuid 程序里要注意);且不检查文件是否存在——路径不存在时返回 -1 并设 errno = ENOENT。
常用模式:
-
access(path, R_OK)→ 检查是否可读(包括目录是否可列出) -
access(path, W_OK)→ 检查是否可写(注意:对目录是“能否在其中创建/删除文件”,不是“能否修改文件内容”) -
access(path, X_OK)→ 检查是否可执行(对目录是“能否 cd 进入”) -
access(path, F_OK)→ 仅检查文件是否存在(不涉及权限)
为什么 access 返回 0 却 open 失败
这是最常踩的坑:权限检查和实际操作之间存在竞态(race condition)。access 和后续 open/fopen 不是原子操作,中间可能被其他进程改权限、删文件、挂载覆盖等。
立即学习“C++免费学习笔记(深入)”;
更安全的做法是直接尝试操作,再根据 errno 判断失败原因:
- 想读?直接
open(path, O_RDONLY),失败看errno == EACCES或ENOENT - 想写?用
O_WRONLY | O_CREAT | O_EXCL配合open,避免被覆盖 - 不要用
access做“预检”后开文件——除非你明确接受竞态风险(比如日志提示“可能不可写”,而非控制流程)
Windows 下 access 行为差异大吗
Windows 的 MSVC CRT 实现了 access(头文件 ),但语义不同:
- 只检查文件系统 ACL 中的「读/写」位,不处理执行权限(
X_OK总是返回 0) - 不检查目录的进入或遍历权限(
X_OK对目录无效) -
R_OK在 Windows 上等价于“文件未设只读属性”,和 Unix 的读权限不是一回事 - 跨平台代码若依赖
access判断执行权或目录遍历权,Windows 上会误判
跨平台项目建议:用 stat + 手动解析 st_mode(Unix)或 GetFileAttributes(Windows)替代 access。
替代方案:stat 检查 st_mode 更可靠吗
是的。stat()能拿到完整权限位,且一次系统调用就获取所有信息,适合需要精确判断的场景。
示例逻辑(Unix):
struct stat sb;
if (stat(path, &sb) == 0) {
bool readable = (sb.st_mode & S_IRUSR) || (sb.st_mode & S_IRGRP) || (sb.st_mode & S_IROTH);
bool writable = (sb.st_mode & S_IWUSR) || (sb.st_mode & S_IWGRP) || (sb.st_mode & S_IWOTH);
}
注意:stat 同样受竞态影响,且不考虑 ACL、capabilities、seccomp 等扩展机制;真正严谨的权限判定必须结合 open 或 execve 的实际返回值。
实际开发中,access 适合快速提示或调试输出;核心逻辑别信它。










