从 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 计算器

相关推荐
做运维的阿瑞1 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
百万蹄蹄向前冲1 小时前
密码都对Node.js却连不上Linux数据库
linux·mysql
彧azz1 小时前
Linux 网络编程学习总结
linux·网络·笔记·学习·面试
susplus2 小时前
【ARM 裸机开发 (IMX6ULL-mini)】GNU工具、Makefile 工程构建、链接脚本详解|C 语言点灯 + 蜂鸣器驱动
linux·arm·makefile·imx6ull
Shadow(⊙o⊙)2 小时前
Linux进阶知识1.0
linux·运维·服务器
>Andre<3 小时前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件
用户0510122572963 小时前
Linux下有关QT显示环境变量设置
linux·嵌入式
闲云自留地3 小时前
告别命令恐惧症,openEuler 基础操作 + 文本 + 网络管理实战
linux·运维·云计算
剑指offer.3 小时前
ARM裸机开发-点亮LED灯
linux·服务器·嵌入式硬件
GeW3 小时前
工作忙.基础弱,也能快速拿RHCE?这套方法亲测有效
linux