1、stat、fstat、lstat函数
本章讨论的中心是三个stat函数以及他们所返回的信息。
#include<sys/stat.h>
int stat(const char * restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *estrict pathname, struct stat *restrict buf);
这三个函数都是返回与指定文件有关的信息。信息保存在struct stat结构中。fstat函数获取已在描述符filedes上打开文件的有关信息。lstat函数类似于stat,但当命名文件是一个符号链接时,它返回的只是该符号链接的有关信息而不是符号链接所指文件的信息。
struct stat 结构的定义如下:struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
2、文件类型
unix的文件类型包括如下几种
(1)普通文件,最常用的文件类型
(2)目录文件
(3)特殊块文件。这种文件类型提供对设备(例如磁盘)带缓冲访问,每次访问以固定长度为单位进行
(4)字符特殊文件
(5)FIFO管道,主要用于进程间通信
(6)套接字
(7)符号链接
文件类型信息包含在st_mode中,可用下表中的宏确定文件类型。
宏 |
文件类型 |
S_ISREG |
普通文件 |
S_ISDIR |
目录文件 |
S_ISCHR |
字符特殊文件 |
S_ISBLK |
块特殊文件 |
S_ISFIFO |
管道或FIFO |
S_ISLNK |
符号链接 |
S_ISSOCK |
套接字 |
例如 :判断文件类型是不是普通文件
S_ISREG(buf.st_mode)。
3、设置用户ID和设置组ID
实际用户ID:表示我们实际上是谁。
实际组ID:实际上属于哪一个组
有效用户ID:决定了我们的文件访问权限,通常是实际用户ID
设置用户ID:将有效用户ID设置成进程所有者的ID,有效ID就成了设置用户ID
4、文件访问权限
用户指的是文件所有者,有三类u表示用户,g表示组,o表示其他,这三类访问权限如下:
st_mode |
意义 |
S_IRUSR |
用户-读 |
S_IWUSR |
用户-写 |
S_IXUSR |
用户-执行 |
S_IRGRP |
组-读 |
S_IWGRP |
组-写 |
S_IXGRP |
组-执行 |
S_IROTH |
其他-读 |
S_IWOTH |
其他-写 |
S_IXOTH |
其他-执行 |
|
|
5、access函数
例如当用open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础进行其访问权限测试,access函数完成了这一功能
#include<unistd.h>
int access(const char *pathname, int mode);成功返回0,出错返回-1
mode是下表中的常量的按位或
mode |
说明 |
R_OK |
测试读权限 |
W_OK |
测试写权限 |
X_OK |
测试执行权限 |
F_OK |
测试文件是否存在 |
6、umask函数
此函数为进程设置文件模式创建屏蔽字,并返回以前的值。
7、chmod和fchmod函数
这两个函数用来改变文件的访问权限
#include<sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode);
成功:返回0,出错返回-1
区别:chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。
改变文件权限的时候,进程的有效用户ID必须等于文件的所有者ID,或者该进程拥有超级用户权限。
这两个函数只是更改i节点最后的更改时间,而不是文件内容的更改时间。
8、chown,fchown,lchown函数
#include<unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int filedes, uid_t owner, gid_t group);
int lchown(const char*pathname, uid_t owner, gid_t group);
这三个函数用来改变文件的用户ID和组ID
成功返回0,出错返回-1
注意:如果文件是符号链接,lchown只更改符号链接本身而不是符号链接所指的文件。
9、文件长度
stat结构成员st_size表示以字节为单位的文件长度,
注意:此字段只对普通文件、目录文件和符号链接有意义。
再注意:对于符号链接,文件的长度是文件名中实际的字节数。
例如 lib -> usr/lib,文件长度是7
10、文件中的空洞
空洞是由所设置的偏移量超过文件尾端,并写某些数据后造成的。
如果使用应用程序(例如cat)复制这种文件,那么这些空洞会被填满,被写为0,
注意:使用cp时,空洞被过滤掉。
11、文件截断
#inclue<unistd.h>
int truncate(const char* pathname, off_t length);
int ftruncate(int filedes, off_t length);
成功返回0,出错返回-1
注意:如果文件长度大于length,超过部分不能再访问,如果文件长度小于length,一般情况下用0填充。
12、文件系统
目前正在使用的UNIX文件系统有多种实现。例如,SOLARIS支持多种不同类型的磁盘文件系统:传统的机遇BSD的unix文件系统,ufs,读写DOS格式哈软盘的文件系统,以及读CD的文件系统。本节讨论的是UFS。
我们可以把一个磁盘氛围一个或者多个分区。每个分区可以包含一个文件系统。如下如图
磁盘、分区和文件系统
关于i节点:
i节点是固定长度的及录项,它包含文件的大部分信息。如果更仔细的观察一个柱面组的i点和数据块部分,则可以看到如下图所示的情况。
注意:
图中有两个目录项指向同一i节点。每个i节点中都有一个链接计数器,其值是指向该i节点的目录项数。只有当链接数减少至0时,才可以删除该文件,有点类似于c++中的智能指针。
每个文件系统各自对他们的i节点进行编号,因此目录项中i节点编号数指向同一文件系统的相应的i节点,不能使一个目录项指向另一个文件系统的i节点。这就是硬链接不能跨文件系统的原因所在。
在不更换文件系统的情况下为一个文件更名时,该文件的实际内容并未移动,只需要构造一个指向现有i节点的新目录项,并解除与旧目录项的链接。例如将文件/usr/lib/foo更名为/usr/foo时,如果他们在同一文件系统中,文件foo的内容无需移动。