【注】*NIX 下很重要的概念是「一切皆文件」;以下仅以 *NIX 家族的起源 UNIX 作为分析对象。
1. 文件的组织与权限表示
1.1 文件的组织方式(此处文件为泛指概念,包括目录等)
文件存在于目录中
目录是一种特殊的文件
-
文件采用层次结构存放
文件的基本操作:open、close、read、write、lseek
打开现存文件或创建新文件,内核都会向进程返回一个文件描述符 fid
对内核而言,所有文件都由文件描述符引用
-
UNIX 下,每个文件都有一个对应的 inode。UNIX 系统中的 inode 结构如下:
以 Ext2 文件系统为例,inode 信息在文件系统的结构层次如下:
【注】stat 命令可以查看文件的 inode 信息。
1.2 文件的权限表示(此处文件为泛指概念,包括目录等)
- 文件的基本权限
- Read 权限:控制读文件权限
- Write 权限:控制写文件权限
- 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 命令可以对已打开的文件更改权限
chmod 745 foo # 将 foo 文件权限数值改为 745(7 4 5 依次对应文件拥有者、文件拥有者所在组、其他人的权限)
- UNIX 中文件权限检查时依次检查拥有者、拥有者所在组、其他用户
1.3 文件的权限要求
- 二进制文件 vs. 脚本文件
- UNIX 下二进制文件执行只需要执行权限即可
- UNIX 下脚本文件执行需要读权限和执行权限
- 权限的特殊性:权限位不是直接授权用户操作某程序,而是授权给用户可以使用相应的系统调用。
比如: 在 UNIX 下的 cat 和 more 命令调用了 read() 系统调用,用户要想使用其显示某文件内容,则必须满足两个权限要求:
- 当前用户需要 cat 和 more 命令的执行权限
- 当前用户需要读取文件的读权限(用于调用 read() 系统调用)
同理: 在 UNIX 下用户要想使用某个命令写文件,也必须满足两个权限要求:
- 当前用户需要写文件的命令的执行权限
- 当前用户需要写文件的写权限(用于调用 write() 系统调用)
- 文件写权限作用
- 改文件名、删除文件不需要对文件有写权限,但需要对文件所在目录具有写权限(故不是文件的拥有者也可以删除相应文件)
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 的权限和所用者信息如下:-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 则可以执行该命令:
-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 位:
- 若既设置了 x 权限又设置了 suid,则显示 s
- 若未设置 x 权限,但设置了 suid,则显示 S
- sgid 位:用于临时将进程的 egid 设置为程序文件的 rgid(类比 suid)
【注】设置了 sgid 后,利用 ls -l 命令显示时 sgid 对应文件拥有者所在组那组 rwx 中的 x 位:
- 若既设置了 x 权限又设置了 sgid,则显示 s
- 若未设置 x 权限,但设置了 sgid,则显示 S
- sticky 位:如果一个可执行程序设置了该位,则该程序执行结束后,程序正文的一个文本被保存在交换区,下次执行该程序时能较快装入内存。如果一个目录设置了该位,则可以保护该目录下的文件不能被轻易删除,只有满足以下条件之一才能删除或更名目录下的文件:
- 拥有此文件
- 拥有此目录
- 是超级用户
【注】设置了 sticky 后,利用 ls -l 命令显示时 sticky 对应其他用户那组 rwx 中的 x 位:
- 若既设置了 x 权限又设置了 sticky,则显示 t
- 若未设置 x 权限,但设置了 sticky,则显示 T
2. 目录的组织与权限表示
2.1 目录的组织
UNIX 目录在文件系统也是作为广泛意义上的文件,只是其中存储的不是文件内容,而是其包含的文件的文件名和对应文件的 inode 指针。
2.2 目录的权限
目录的读权限位:仅能显示目录下的文件名(不能访问文件的 inode 指针)
目录的执行权限位:可以遍历目录内的文件属性信息(可以访问文件的 inode 指针)
目录的写权限位 + 执行权限位:可以在目录下创建/删除文件(不要求对文件具有权限)
- 目录拥有者对目录没有执行权限:不能访问目录下的文件(即使对文件具有权限)
- 用户对目录具有读权限,无执行权限:只能运行 ls DIR 而不能运行 ls -l DIR
- 用户对目录拥有执行权限,无读权限:可运行 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。
- 专用进程
- 进程 ID = 0 是调度进程(交互进程),是内核的一部分,称作系统进程
- 进程 ID = 1 是 init 进程,对应与 /sbin/init 。此进程负责在内核自举后启动一个 UNIX 系统,并将系统引导到一个状态(与初始化文件 /etc/rc* 相关)
- fork 函数:内核创建新进程(子进程)
- 函数调用一次,返回两次:子进程返回 0,父进程返回子进程 ID
- fork 创建的子进程是父进程的复制品,子进程获得父进程的数据空间、堆、栈的复制品(而不是共享这些存储空间)
- 父子进程的执行顺序不确定,取决于内核的调度算法
4.4 文件共享
UNIX 支持在不同进程间共享打开文件。内核使用三个数据结构,使多个进程共享一个文件。
- 每个进程在进程表中都有一个记录项,每个记录项中包含一张打开文件描述符,包含:
- 文件描述符标志
- 指向一个文件表项的指针
- 内核为所有打开文件维持一张文件表,包含:
- 文件状态标志:读、写、增写、同步等
- 当前文件位移量
- 指向该文件 v 节点表项