从 chmod 755 说起:Unix 文件权限到底是怎么算的?

刚学 Linux 的时候,很多人都背过「755 是 rwxr-xr-x,644 是 rw-r--r--」。

但说真的,你有没有想过------为什么读是 4,写是 2,执行是 1?为什么 7 就代表 rwx?这三个数字到底是怎么拼出来的?

这篇文章不讲 chmod 命令怎么用(那个 man 手册写得更清楚),而是聊清楚权限数字背后的位运算逻辑,以及怎么用代码实现一个权限计算器。

权限的二进制本质

Unix 的权限系统其实就三组、每组三位,对应三个角色:

每组三位分别表示 r(读)、w(写)、x(执行),用二进制表示就是:

bash 复制代码
rwx  →  111  →  7
rw-  →  110  →  6
r--  →  100  →  4
---  →  000  →  0

所以 755 的完整含义是:

bash 复制代码
Owner:  rwx  →  7  →  111
Group:  r-x  →  5  →  101
Others: r-x  →  5  →  101

本质就是把三组三位二进制数(每组 0-7),拼成一个三位八进制数。所以叫 chmod,change file mode bits,一个比特都不浪费。

面试最爱问的 umask

理解了二进制本质,umask 就很好懂了。umask 表示要屏蔽哪些权限位:

bash 复制代码
# 当前 umask
$ umask
0022

# 新文件默认权限 = 666 & (~022) = 644
# 新目录默认权限 = 777 & (~022) = 755

因为文件默认不应该有执行权限(除非显式指定),所以文件基数是 666,目录是 777。umask = 0022 就是把 group 和 others 的写权限去掉。

对应的位运算:

bash 复制代码
function applyUmask(base: number, umask: number) {
  return base & (~umask)
}
// 文件: 0o666 & (~0o022) = 0o644
// 目录: 0o777 & (~0o022) = 0o755

权限计算的核心实现

回到 chmod 计算器的实现。把八进制转成权限矩阵,本质就是做三次位测试:

bash 复制代码
type Permission = 'r' | 'w' | 'x'
type Scope = 'owner' | 'group' | 'others'

function octalToPerms(octal: string) {
  const digits = octal.split('').map(Number)
  // 三个 digit 分别对应 owner/group/others
  // 每个 digit 的二进制位对应 r/w/x
  const scopes = ['owner', 'group', 'others']
  return scopes.map((scope, i) => {
    const d = digits[i]
    return {
      r: (d & 4) !== 0,  // 检查第 3 位
      w: (d & 2) !== 0,  // 检查第 2 位
      x: (d & 1) !== 0,  // 检查第 1 位
    }
  })
}

权限转回八进制就更直接了,就是加权求和:

bash 复制代码
function permsToOctal(perms) {
  let v = 0
  if (perms.r) v += 4
  if (perms.w) v += 2
  if (perms.x) v += 1
  return v
}

这其实就是教科书里的「按权展开」------每个 bit 的权重分别为 4、2、1。

两个经常被忽略的特殊权限

setuid(4000)和 setgid(2000)

八进制权限其实是四位,最高位控制特殊行为:

  • 4 = setuid:以文件所有者的身份执行(典型的如 /usr/bin/passwd 需要 root 权限改密码)
  • 2 = setgid:以文件所属组的身份执行
  • 1 = sticky bit:限制目录中文件的删除权限(/tmp 目录就是典型的例子)
bash 复制代码
# 给程序设置 setuid
chmod 4755 some-program

# 查看效果
$ ls -l some-program
-rwsr-xr-x  1 root  staff  some-program  # s 代替了 owner 的 x

注意这里的 4(setuid)和权限计算中的 4(read)含义完全不同------一个是控制位,一个是数据位。因为 setuid 只对 owner 的 execute 位有意义,如果 owner 没有 x 权限,setuid 会变成大写的 S(表示无效)。

sticky bit(1000)

bash 复制代码
chmod 1777 /tmp
# drwxrwxrwt 中的 t 表示 sticky bit 已设置

设置了 sticky bit 的目录,用户只能删除自己的文件------这在多用户系统中防止乱删文件。

记忆技巧

三个特殊权限位的数值 4/2/1 和普通权限位完全一样,唯一的区别是作用范围不同:

bash 复制代码
特殊位: SUID(4) | SGID(2) | Sticky(1)
普通位: Read(4) | Write(2) | Execute(1)

如果你记得 4+2+1=7 是 rwx,那 4+2+1=7 就是所有特殊权限同时开启------结构完全一致。

最终效果

基于上面的逻辑,做了一个可视化的权限计算器:chmod 计算器

功能包括:

  • 通过勾选任意修改权限
  • 实时显示八进制和符号表示
  • 内置 755/644/600/700 等预设
  • 直接复制 chmod 命令

权限本身不复杂,本质就是三位二进制数,但要做好工具还是需要把位运算逻辑处理清楚。希望对你理解 chmod 有帮助。


相关工具:Linux 命令速查 | HTTP 状态码 | IP 计算器

相关推荐
天启HTTP3 分钟前
爬虫防封核心原理:IP轮换机制与风控规避逻辑
linux·服务器·网络·爬虫·tcp/ip
广州浮点FLOATLIC2 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
BLUcoding3 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom
AIgorithmGEEK3 小时前
[Linux]从手写报头到内核套路:序列化、反序列化与自定义协议全链路
linux·运维·服务器·网络·序列化·反序列化
Nil2083 小时前
leetcode 139单词拆分
linux·运维·服务器
Starry-sky(jing)3 小时前
BUG: unable to handle kernel paging request 完整排查:dmesg 四要素与三路定罪
linux·运维·服务器·内核·排障
mounter6253 小时前
从硬件互连到操作系统变革:CXL 技术演进与 Linux 内核工程挑战
linux·运维·服务器
xh didida4 小时前
Linux -- 基础IO
linux·服务器·开发语言·c++
zly35005 小时前
centos7 mount设备挂载 /dev/sda1/硬盘挂载
linux·运维·服务器
工业一体机老司机6 小时前
工业一体机选购后的系统部署:Ubuntu下Docker容器化运行与GPIO配置
linux·ubuntu·docker·人机交互