【注】*NIX 下很重要的概念是「一切皆文件」;以下仅以 *NIX 家族的起源 UNIX 作为分析对象。

1. 文件的组织与权限表示

1.1 文件的组织方式(此处文件为泛指概念,包括目录等)

  • 文件存在于目录中

  • 目录是一种特殊的文件

  • 文件采用层次结构存放

  • 文件的基本操作:open、close、read、write、lseek

  • 打开现存文件或创建新文件,内核都会向进程返回一个文件描述符 fid

  • 对内核而言,所有文件都由文件描述符引用

  • UNIX 下,每个文件都有一个对应的 inode。UNIX 系统中的 inode 结构如下:

以 Ext2 文件系统为例,inode 信息在文件系统的结构层次如下:

【注】stat 命令可以查看文件的 inode 信息。

1.2 文件的权限表示(此处文件为泛指概念,包括目录等)

  • 文件的基本权限
  1. Read 权限:控制读文件权限
  2. Write 权限:控制写文件权限
  3. Execute 权限:控制将文件调入内存执行
  • 文件的基本权限位

其中,r 代表 Read 权限,w 代表 Write 权限,x 代表 Execute 权限。rwx 权限位组合在一起用来表示文件具有的基本权限,可使用 ls -l 命令列出文件的基本权限位信息,在对应位若为 -,则表明不具有对应位权限;若为对应 r\w\x 字母,则表明具有对应权限。每组 rwx 权限位组合对应的权限数值如下表(对应权限位为 0 代表不具有该权限,为 1 代表具有该权限):

r w x 权限数值
0 0 0 0
0 0 1 1
0 1 0 2
0 1 1 3
1 0 0 4
1 0 1 5
1 1 0 6
1 1 1 7
  • UNIX 中 chmod 命令可以更改文件权限;fchmod 命令可以对已打开的文件更改权限
1
chmod 745 foo       # 将 foo 文件权限数值改为 745(7 4 5 依次对应文件拥有者、文件拥有者所在组、其他人的权限)
  • UNIX 中文件权限检查时依次检查拥有者、拥有者所在组、其他用户

1.3 文件的权限要求

  • 二进制文件 vs. 脚本文件
  1. UNIX 下二进制文件执行只需要执行权限即可
  2. UNIX 下脚本文件执行需要读权限和执行权限
  • 权限的特殊性:权限位不是直接授权用户操作某程序,而是授权给用户可以使用相应的系统调用。

比如: 在 UNIX 下的 cat 和 more 命令调用了 read() 系统调用,用户要想使用其显示某文件内容,则必须满足两个权限要求:

  1. 当前用户需要 cat 和 more 命令的执行权限
  2. 当前用户需要读取文件的读权限(用于调用 read() 系统调用)

同理: 在 UNIX 下用户要想使用某个命令写文件,也必须满足两个权限要求:

  1. 当前用户需要写文件的命令的执行权限
  2. 当前用户需要写文件的写权限(用于调用 write() 系统调用)
  • 文件写权限作用
  1. 改文件名、删除文件不需要对文件有写权限,但需要对文件所在目录具有写权限(故不是文件的拥有者也可以删除相应文件)

1.4 文件的特殊权限

除了上述说明的三组 rwx 共 9 位权限位外,UNIX 下文件还具有另外 3 位特殊权限位:suid\sgid\sticky。该三位特殊权限位组成一组,使用 chmod 命令时该组权限值放在最前面:chmod 4755 xxx 其中 4 即为该组特殊权限位组。

  • suid 位:用于临时将进程的 euid 设置为程序文件的 ruid

【注】用户运行程序后是该进程的拥有者(ruid),进程执行者(euid)代表该进程以相应身份访问系统资源。若位设置 suid 位,ruid 和 euid 均为当前用户 id;设置了 suid 位后,ruid 仍为当前用户 id,euid 为该程序文件的拥有者 id。(ruid、euid 解释见下文 4

比如: 用户 Jane 运行命令 view memo.txt,view 和 memo.txt 的权限和所用者信息如下:

1
2
-rwx--x--x 1 root bin 4515 Aug 14 13:08   # view
-rw------- 1 root bin 218 Aug 14 13:08 # memo.txt

由于 Jane 用户运行 view 程序时对应的进程的 euid 为 Jane 用户 id,而 Jane 对 memo.txt 文件不具备可读权限,故无法执行。但利用 chmod 命令将 view 程序的权限改为 4755 则可以执行该命令:

1
2
-rws--x--x 1 root bin 4515 Aug 14 13:08   # view
-rw------- 1 root bin 218 Aug 14 13:08 # memo.txt

原因在于设置了 suid 后,Jane 用户运行 view程序时对应的进程的 euid 为 view 程序文件的拥有者 root 的 id,而 root 用户具备对 memo.txt 文件的可读权限,故该命令可以正常执行。

【注】设置了 suid 后,利用 ls -l 命令显示时 suid 对应文件拥有者那组 rwx 中的 x 位:

  1. 若既设置了 x 权限又设置了 suid,则显示 s
  2. 若未设置 x 权限,但设置了 suid,则显示 S
  • sgid 位:用于临时将进程的 egid 设置为程序文件的 rgid(类比 suid)

【注】设置了 sgid 后,利用 ls -l 命令显示时 sgid 对应文件拥有者所在组那组 rwx 中的 x 位:

  1. 若既设置了 x 权限又设置了 sgid,则显示 s
  2. 若未设置 x 权限,但设置了 sgid,则显示 S
  • sticky 位:如果一个可执行程序设置了该位,则该程序执行结束后,程序正文的一个文本被保存在交换区,下次执行该程序时能较快装入内存。如果一个目录设置了该位,则可以保护该目录下的文件不能被轻易删除,只有满足以下条件之一才能删除或更名目录下的文件:
  1. 拥有此文件
  2. 拥有此目录
  3. 是超级用户

【注】设置了 sticky 后,利用 ls -l 命令显示时 sticky 对应其他用户那组 rwx 中的 x 位:

  1. 若既设置了 x 权限又设置了 sticky,则显示 t
  2. 若未设置 x 权限,但设置了 sticky,则显示 T

2. 目录的组织与权限表示

2.1 目录的组织

UNIX 目录在文件系统也是作为广泛意义上的文件,只是其中存储的不是文件内容,而是其包含的文件的文件名和对应文件的 inode 指针。

2.2 目录的权限

  • 目录的读权限位:仅能显示目录下的文件名(不能访问文件的 inode 指针)

  • 目录的执行权限位:可以遍历目录内的文件属性信息(可以访问文件的 inode 指针)

  • 目录的写权限位 + 执行权限位:可以在目录下创建/删除文件(不要求对文件具有权限)

  1. 目录拥有者对目录没有执行权限:不能访问目录下的文件(即使对文件具有权限)
  2. 用户对目录具有读权限,无执行权限:只能运行 ls DIR 而不能运行 ls -l DIR
  3. 用户对目录拥有执行权限,无读权限:可运行 ls -l DIR/FILE 而不能运行 ls DIR

【注】在 UINX 中,目录的权限不具有继承性,即不能被子目录继承。故访问一个路径下的文件时,需要整个路径上的目录都具有执行权限。

3. 文件链接

3.1 文件硬链接

每个 inode 节点都有一个链接计数,表示指向该 inode 节点的 inode 指针数。只有当链接计数减少为 0 时,才表示删除了该文件。链接计数表示的是该文件拥有的硬链接数,创建硬链接时,系统不会为它重新分配 inode,而是在目录下直接添加一个指向文件 inode 节点的 inode 指针项。

  • 创建硬链接:link 命令
  • 删除硬链接:unlink 命令
  • 删除文件:UNIX 下删除文件是删除文件的硬链接,而并非释放该文件占用的磁盘块,只有当一个文件的硬链接数减为 0 时,该文件才彻底从文件系统中删除了(即无法访问到了)

【注】硬链接不可以在不同文件系统间建立。对于目录的硬链接,只有超级用户可以创建。

3.2 文件软链接(符号链接)

对一个 inode 节点的间接指针,不同于硬链接,容易被清除。创建符号链接时,系统会分配一个新的 inode 节点,所以符号链接的 inode 号和文件的 inode 号不相同。符号链接中的 inode 里存放者指向文件的路径,当文件的被删除时,符号链接也就失效了。

【注】符号链接可以跨文件系统建立。任何用户均可创建文件的符号链接。

4. 用户、主体和客体

4.1 用户标识

UNIX 系统中,每个用户有一个唯一的 UID。

  • root 用户的 UID :0
  • 用户不能更改其用户 UID
  • 内核根据 UID 检验其权限
  • /etc/passwd 文件:保存用户名和用户 ID 映射关系

同时,用户可以属于某一个组,组 ID 是系统管理员分配的。

  • 同组中的成员之间可以共享资源
  • /etc/group 文件:保存组用户和组 ID 映射关系
  • 一个用户可以属于多个组

4.2 主体

  • 用户访问文件,具体的操作由主体执行,主体是进程
  • 当一个主体访问文件时,需要知道其以哪个用户身份访问
  • 进程是主体,进程保存相关联的用户信息
ID 说明
ruid rgid 在登录系统时取自口令文件中的登录项
euid egid 用于文件存取许可权检查,决定了对文件的访问权
suid sgid 由 exec 函数保存,保存了 euid 和 egid 的副本

【注】此 suid 非上文说到的文件权限 suid 位。

4.3 进程控制

每个进程拥有一个非负整数的唯一进程 ID。

  • 专用进程
  1. 进程 ID = 0 是调度进程(交互进程),是内核的一部分,称作系统进程
  2. 进程 ID = 1 是 init 进程,对应与 /sbin/init 。此进程负责在内核自举后启动一个 UNIX 系统,并将系统引导到一个状态(与初始化文件 /etc/rc* 相关)
  • fork 函数:内核创建新进程(子进程)
  1. 函数调用一次,返回两次:子进程返回 0,父进程返回子进程 ID
  2. fork 创建的子进程是父进程的复制品,子进程获得父进程的数据空间、堆、栈的复制品(而不是共享这些存储空间)
  3. 父子进程的执行顺序不确定,取决于内核的调度算法

4.4 文件共享

UNIX 支持在不同进程间共享打开文件。内核使用三个数据结构,使多个进程共享一个文件。

  • 每个进程在进程表中都有一个记录项,每个记录项中包含一张打开文件描述符,包含:
  1. 文件描述符标志
  2. 指向一个文件表项的指针
  • 内核为所有打开文件维持一张文件表,包含:
  1. 文件状态标志:读、写、增写、同步等
  2. 当前文件位移量
  3. 指向该文件 v 节点表项