3. 设备节点权限基础:文件权限(rwx)、用户/组/其他、权限位(0666/0644/0660)的含义

在 Linux 系统中,设备节点(Device Node)本质上是位于 /dev 目录下的特殊文件。HAL 驱动调试过程中,应用层无法打开设备节点、ioctl 调用返回 Permission denied,绝大多数情况都是因为设备节点的权限配置不正确。理解文件权限模型是正确配置设备节点的前提。

3.1 文件权限的三元组:rwx

Linux 使用 9 个字符表示一个文件或设备节点的权限,分为三组,每组三个字符:

分组 字符位置 权限位 含义 数值
所有者(User) 2-4 r w x 读、写、执行 4 2 1
所属组(Group) 5-7 r w x 读、写、执行 4 2 1
其他用户(Others) 8-10 r w x 读、写、执行 4 2 1

对于设备节点,读(r) 允许读取设备数据;写(w) 允许向设备发送数据或控制命令;执行(x) 通常对设备节点无意义,但在某些驱动框架(如 UIO)中用于表示允许 mmap 操作。

调试要点: HAL 层通常需要同时具备 r 和 w 权限才能完成 open、read、write、ioctl 等操作。缺少写权限时,ioctl 调用会直接返回 -EACCES。

3.2 用户/组/其他:三权分立模型

每个设备节点都关联一个 所有者(UID) 和 所属组(GID)。系统根据进程的 有效用户 ID(EUID) 和 有效组 ID(EGID) 决定访问权限:

  • 所有者(User):设备节点的创建者,通常是 root。拥有最高控制权。
  • 所属组(Group):通常将需要访问该设备的用户加入同一个组(如 gpio、i2c、video),实现组内共享。
  • 其他(Others):既不是所有者也不属于所属组的用户。调试阶段通常设为 --- 以限制非授权访问。
最佳实践: 在 HAL 驱动调试中,建议将调试用户加入 root 组或设备专用组,避免将设备节点权限设为 0777,防止安全漏洞。
设备节点访问控制模型 设备节点 /dev/xxx 所有者 (User) UID = root rwx (7) 所属组 (Group) GID = gpio rwx (7) 其他 (Others) --- (0) 进程 EUID 匹配 UID 则使用所有者权限 进程 EGID 匹配 GID 则使用所属组权限

3.3 权限位数值表示:0666 / 0644 / 0660

权限位使用 八进制数 表示,每个数字对应一组权限(User / Group / Others),数字为各组权限值的累加和:

权限位 二进制 User Group Others 典型用途
0666 110 110 110 rw- (6) rw- (6) rw- (6) 所有用户可读写(调试阶段临时使用)
0644 110 100 100 rw- (6) r-- (4) r-- (4) 所有者读写,其他只读(普通文件默认)
0660 110 110 000 rw- (6) rw- (6) --- (0) 所有者与所属组读写,其他无权限(推荐设备节点)
0600 110 000 000 rw- (6) --- (0) --- (0) 仅所有者可读写(安全敏感设备)
安全警告: 切勿在生产环境中使用 0666 或 0777。调试完成后,应立即将设备节点权限恢复为 0660 或 0600,并确保所属组只包含受信任的用户。

3.4 设备节点权限查看与修改

使用 ls -l 查看设备节点权限:

$ ls -l /dev/gpiochip0
crw-rw---- 1 root gpio 254, 0 Apr  1 10:30 /dev/gpiochip0

输出解析:

  • c:字符设备(b 为块设备)
  • rw-rw----:所有者 rw-,所属组 rw-,其他 ---
  • 1:硬链接数
  • root:所有者
  • gpio:所属组
  • 254, 0:主设备号、次设备号

使用 chmod 修改权限,chown 修改所有者/组:

# 修改权限为 0660
sudo chmod 660 /dev/gpiochip0

# 修改所有者为 root,所属组为 gpio
sudo chown root:gpio /dev/gpiochip0

# 将当前用户加入 gpio 组(需重新登录生效)
sudo usermod -aG gpio $USER

3.5 设备节点权限与 HAL 驱动调试的关联

在 HAL 驱动调试中,权限配置直接影响调试效率:

调试场景 推荐权限 原因
内核驱动开发阶段 0660,组设为 root 仅 root 可操作,避免多进程干扰
HAL 层集成调试 0660,组设为 system 或 hal HAL 进程以 system 组运行,需要读写权限
应用层快速验证 0666(临时) 跳过权限检查,快速验证驱动功能
生产部署 0660 或 0600 最小权限原则,仅授权进程可访问
调试技巧: 在 init.rc 或 udev 规则中,可以为特定设备节点设置 MODE="0660"、GROUP="hal",确保设备节点在创建时自动应用正确的权限配置,避免每次手动修改。
权限位数值计算与映射 权限位数值计算示例:0660 八进制 0 特殊权限位 八进制 6 User: rw- 八进制 6 Group: rw- 八进制 0 Others: --- 二进制: 110 二进制: 110 二进制: 110 二进制: 000 最终权限字符串 crw-rw---- c = 字符设备 b = 块设备

3.6 常见权限配置错误与排查

  • 错误 1: 设备节点权限为 0644,HAL 进程尝试 ioctl 失败。
    原因: 缺少写权限。ioctl 通常需要 w 权限。
    解决: 改为 0660 并确认 HAL 进程在正确的组中。
  • 错误 2: 使用 sudo 可以访问,但普通用户无法访问。
    原因: 设备节点所属组未包含用户,或 Others 权限为 ---。
    解决: 将用户加入设备所属组,或调整组权限。
  • 错误 3: ls -l 显示权限正确,但应用仍返回 Permission denied。
    原因: SELinux 或 AppArmor 等 LSM 模块拦截。
    解决: 检查 audit.log 或临时设置为宽容模式(permissive)进行验证。
快速排查命令:
ls -l /dev/xxx — 查看当前权限
id — 查看当前用户 UID/GID 及所属组
sudo cat /sys/kernel/debug/device/xxx/permissions — 某些内核驱动提供调试接口