1 简介
之前学习了执行I/O操作的基本函数,主要是围绕普通文件I/O的打开、读或写。下面继续学习Unix文件系统的其他特征和文件的基本性质。我们将从stat函数开始,了解stat结构所代表的文件属性,了解Unix文件系统的结构和符号链接,最后学习对目录进行操作的各个函数。
2 stat、fstat和lstat函数
本章讨论的重点都是围绕着这3个stat函数以及他们返回的信息。
#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf) ;
int lstat(const char *pathname, struct stat *buf) ;
/*三个函数的返回:若成功则为0,若出错则为-1*/
stat函数返回一个以pathname命名的文件有关的信息结构。
fstat函数返回一个在描述符fd上打开的文件有关信息结构。
lstat函数类似于stat,但但以pathname命名的文件是一个符号链接时,lstat将返回该符号链接本身的相关信息,而不是它指向的文件的相关信息。
第二个参数buf是指针,它指向一个stat的结构体,该结构的实际定义可能随实现而有所不同,但其基本形式是:
该结构中的每一个成员都是基本系统数据类型。
3 文件类型
(1)普通文件(regularfile)。这是最常见的文件类型,这种文件包含了某种形式的数据。至于这种数据是文本还是二进制数据对于内核而言并无区别。对普通文件内容的解释由处理该文件的应用程序进行。
(2)目录文件(directoryfile)。这种文件包含了其他文件的名字以及指向与这些文件有关信息的指针。对一个目录文件具有读许可权的任一进程都可以读该目录的内容,但只有内核可以写目录文件。
(3)字符特殊文件(characterspecialfile)。这种文件用于系统中某些类型的设备。
(4)块特殊文件(blockspecialfile)。这种文件典型地用于磁盘设备。系统中的所有设备或者是字符特殊文件,或者是块特殊文件。
(5)FIFO。这种文件用于进程间的通信,有时也将其称为命名管道。
(6)套接口(socket)。这种文件用于进程间的网络通信。套接口也可用于在一台宿主机上的进程之间的非网络通信。第15章将用套接口进行进程间的通信。
文件类型都包含在stat结构中的stat_mode成员中。可在<sys/stat.h>中找到文件类型宏:
宏 | 文件类型 |
S_ISREG() | 普通文件 |
S_ISDIR() | 目录文件 |
S_ISCHR() | 字符特殊文件 |
S_ISBLK() | 块特殊文件 |
S_ISFIFO() | 管道或FIFO |
S_ISLNK() | 符号链接 |
S_ISSOCK() | 套接字 |
4 文件访问权限
与一个进程相关的ID有6个或更多:
实际用户ID | 该用户是谁 |
实际组ID | |
有效用户ID | 文件访问权限 |
有效组ID | |
附加组ID | |
保存的设置用户ID | 由exec函数保存 |
保存的设置组ID |
通常,有效用户ID等于实际用户ID,有效组ID等于实际组ID。
设置用户ID位及设置组ID位都包含在st_mode值中,这两位可以用常量S_ISUID和S_ISGID测试。
st_mode值也包含了针对文件的访问权限位。所有文件类型(包括目录文件、字符特别文件等)都有访问权限。
st_mode屏蔽 | 意义 |
S_IRUSR | 用户-读 |
S_IWUSR | 用户-写 |
S_IXUSR | 用户-执行 |
S_IRGRP | 组-读 |
S_IWGRP | 组-写 |
S_IXGRP | 组-执行 |
S_IROTH | 其他-读 |
S_IWOTH | 其他-写 |
S_IXOTH | 其他-执行 |
我们用名字打开任一类型的文件时,对该名字中包含的每一个目录,包括它可能隐含的当前工作目录都应具有执行权限。
进程每次打开、创建或删除一个文件,内核就进行文件访问权限测试:
- 若进程的有效用户ID是0(超级用户),则允许访问
- 若进程的有效用户ID等于文件所有者ID,
- 进程的有效组ID或附加组ID之一等于文件的组ID,
- 其他用户被设置,
- 那么若适当的访问权限位被设置,则允许访问,否则拒绝访问