linux系统编程_文件系统
- ext2文件系统:
super block | GDT | block bitmap | inode bitmap | inode table | data blocks(一个block组的主要部分) |
(1)inode
:其本质为结构体,存储文件的属性信息。如:权限、类型、大小、时间、用户、盘块位置……也叫作文件属性管理结构,大多数的inode都存储在磁盘上,少量常用、近期使用的inode会被缓存到内存中。
(2)dentry
:目录项,其本质依然是结构体,重要成员变量有两个 {文件名,inode, …},而文件内容(data)保存在磁盘盘块中。注意:创建一个文件的硬链接其实就是增加一个该文件的dentry,不会改变该文件的inode个数,更不会影响该文件的data block。
- 文件操作:
(3)使用系统调用stat
查看文件类型时有一个问题,若它的参数是一个符号链接(软链接),那么stat会穿透该符号链接追踪到实际真正的文件并给出该实际文件的类型而非符号链接的类型。而lstat
函数就不会出现穿透符号链接的问题,它会给出符号链接的文件类型。
(4)struct stat
结构体是系统维护的一个描述文件信息的结构体,其中st_mode
保存文件的类型、权限等信息,注意,st_mode也是一个位图(bitmap
),共有16位,前四位描述文件类型,接下来三位描述超级权限,再接下来的9位每三位一组描述用户、组、其他人的读\写\执行权限。通常,使用系统调用stat
查看文件大小、文件类型以及文件权限等。详细信息参见man page中关于stat的介绍。
(5)上述(4)中的三位超级权限位从左到右依次是:setGID(设置组ID位)
、setID(设置用户ID位)
、黏住位。黏住位是针对以前计算机内存较小时的情况设计的,现已摒弃;关于setID
位,需要进一步区分进程的两个ID:有效ID(EID)和实际ID(UID)。
(6)unlink
函数的作用实际上是减少一个文件的dentry到inode的链接数。因此,我们删除文件,从某种意义上说,只是让文件具备了被释放的条件。unlink函数的特征:清除文件时,如果文件的硬链接数到0了,没有dentry对应,但该文件仍不会马上被释放。要等到所有打开该文件的进程关闭该文件,系统才会挑时间将该文件释放掉。注意:若在unlink
之后继续对该文件执行write
操作,程序并不会出错,因为系统调用是通过文件结构体来访问文件,不通过dentry
路径来访问;况且,对文件的写操作也并不是直接写到文件中,而是写到操作系统的内核缓冲区中。
(7)隐式回收:当进程结束运行时,所有该进程打开的文件会被关闭,申请的内存空间会被释放。所以,例如在一个程序中使用malloc
申请的动态内存空间即使在后面忘记free
掉也没关系,程序结束后会自动释放掉,但若该程序一直不结束那么就有内存泄露的风险,比如在服务器程序中要格外注意这一点。
- 目录操作:
(8)文件和目录的权限比较:
类别\权限 | r | w | x |
---|---|---|---|
文件 | 文件的内容可以被查看:cat、more、less… | 内容可以被修改:vi、> … | 可以运行产生一个进程:./文件名 |
目录 | 目录可以被浏览:ls、tree… | 创建、删除、修改文件:mv、touch、mkdir… | 可以被打开、进入:cd |
注意:目录文件也是“文件”。其文件内容是该目录下所有子文件的目录项(dentry
)。 可以尝试用vim打开一个目录,里面的内容就是一个个的dentry
。所以,目录和普通文件其实没有区别。
(9)opendir
、readdir
、clodedir
目录操作函数。
(10)递归遍历目录
(11)重定向:dup
和dup2
函数,需从文件描述符的原理上理解,尤其是dup2
函数。
(12)虚拟文件系统(VFS):把不同的文件系统统一成相同的格式,屏蔽不同文件系统之间的差别。注意,windows系统中没有VFS,所以假如一台电脑中同时装有windows和linux双系统,那么在windows下看不到linux中的文件,而在linux下可以看到windows下的文件甚至可以操作它们,就是因为linux下的VFS。如下的VFS过程理解即可,实际开发中应用不多。
VFS虚拟文件系统:
以不同的进程打开文件为例: