正确:chmod()需传绝对路径或有效相对路径,mode为八进制整数(如0755),失败返回-1并设errno;不改所有权,setuid/setgid位由非root用户修改时会被自动清除。

用 chmod() 修改文件权限要传对路径和模式
Linux 下改文件权限最直接的方式就是调用 chmod() 系统调用,但它不接受相对路径的“当前工作目录解析”——必须传绝对路径或相对于进程当前目录的有效路径。如果传了错误路径(比如文件不存在、路径含符号链接未解引用、权限不足),chmod() 会失败并返回 -1,errno 设为 ENOENT、EACCES 或 EPERM。
实操建议:
-
chmod()第二个参数是整型 mode,不是字符串(别写成"755");正确写法是0755(八进制字面量)或S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH - 路径字符串必须以
\0结尾,不能是 std::string::c_str() 之后被意外修改的临时缓冲区(常见于局部std::string在函数末尾析构) - 若目标是符号链接本身(而非它指向的文件),需用
chmod();若想改链接目标的权限,得先readlink()+chmod(),或直接用stat()判断类型再决定是否解引用
chmod() 不影响文件所有者,但可能因 setuid/setgid 被忽略
调用 chmod() 只能修改权限位(rwx),无法更改文件所有者或所属组——那是 chown() 的事。但有个关键例外:如果文件设置了 setuid(S_ISUID)或 setgid(S_ISGID)位,且调用者不是 root,chmod() 在修改权限时会自动清除这两个特殊位(除非显式重设)。
这意味着:
- 普通用户执行
chmod 644 file实际得到的是644,不是4644(哪怕原文件有 setuid) - 要保留 setuid,必须在 mode 中显式包含
S_ISUID,例如:chmod(path.c_str(), 04644) - root 用户不受此限制,可以任意设置/保留这些位
用 std::filesystem::permissions() 更安全但有兼容性陷阱
C++17 引入了 std::filesystem::permissions(),封装了底层系统调用,语义更清晰,且自动处理路径规范化。但它默认行为是“替换”权限(std::filesystem::perm::replace),而不是“修改”(std::filesystem::perm::add / std::filesystem::perm::remove)。很多开发者误以为它像 shell 的 chmod +x 一样叠加,结果覆盖掉了原有读写位。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
常见误用场景:
- 写
fs::permissions(p, fs::perms::owner_exec)→ 实际只保留 owner-exec,其他全清零 - 正确叠加执行权限:用
fs::permissions(p, fs::perms::owner_exec, fs::perm_options::add) - GCC 8+ 和 Clang 7+ 支持完整功能;MSVC 2019 16.3+ 才支持 Linux 下的
permissions(),旧版本会静默失败或抛异常
权限修改失败时,errno 比返回值更重要
chmod() 成功返回 0,失败返回 -1 —— 但仅靠这个无法定位问题。真正有用的线索藏在全局 errno 里。比如 EACCES 表示路径中某一级目录无执行权限(即无法进入该目录),而不是目标文件没权限;EROFS 表示文件系统只读(如挂载了 ro);EPERM 多见于尝试修改 root 所有文件却非 root 进程。
调试建议:
- 永远检查
if (chmod(...) == -1) { perror("chmod"); /* 或 log errno */ } - 不要依赖
strerror(errno)直接展示给用户——某些 errno(如EINTR)在重试后可恢复,不应视为最终错误 - 对关键路径,先用
access(path.c_str(), W_OK)预检写权限(注意:access()检查的是真实 UID/GID,不是有效 UID/GID,和chmod()实际行为略有差异)
权限变更是否生效,不仅取决于调用成功,还受父目录执行权限、挂载选项、SELinux/AppArmor 等上下文约束——这些不会让 chmod() 报错,但会让后续 open() 或 execve() 失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










