声明:本Linux文件系统博客,共分四节,是根据网上多个相关博客,以及自己的理解加上相关资料总结而成。(作者:lvyilong316)
系统中的每一个进程都有自己的一组打开的文件 ,像根文件系统,当前目工作目录,安装点等。有四个数据结构将VFS层和系统的进程紧密联系在一起,它们分别是:files_struct,fs_struct,file_system_type 和namespace结构体。
我们先看两个图:
1.files_struct
文件描述符是用来描述打开的文件的。每个进程用一个files_struct结构来记录文件描述符的使用情况,这个结构称为用户打开文件表(含有描述符表)。它是进程的私有数据。
1.1数据结构
files_struct 结构体定义在文件 include/linux/fdtable.h该结构体由进程描述符中的files 域指向。所有与每个进程相关的信息如打开的文件及文件描述符都包含在其中。
44struct files_struct {//文件描述符表
45 /*
46 * read mostly part
47 */
48 atomic_t count; //共享该表的进程数
49 struct fdtable *fdt;
50 struct fdtable fdtab; //定义了文件的一些属性
51 /*
52 * written part on a separate cache line in SMP
53 */
54 spinlock_t file_lock ____cacheline_aligned_in_smp;
55 int next_fd; //下一个文件描述符
56 struct embedded_fd_set close_on_exec_init; //*exec()关闭的文件描述符
57 struct embedded_fd_set open_fds_init; //文件描述符的初始集合
58 struct file * fd_array[NR_OPEN_DEFAULT]; //默认的文件对象数组
59};
1. 看看 struct fdtable结构:
struct fdtable {//位于struct files_struct中
unsigned int max_fds; //文件对象的上限
struct file ** fd; //全部文件对象数组
fd_set *close_on_exec; //*exec()关闭的文件描述符
fd_set *open_fds; //指向打开文件的描述符
struct rcu_head rcu;
struct fdtable *next; //指向该链表的下一个对象
};
2. fd数组指针指向已打开的文件对象链表,默认情况下,指向fd_arry数组。因为NR_OPEN_DEFAULT等于32,所以该数组可以容纳32个文件对象。如果一个进程所打开的文件对象超过32个。内核将分配一个新数组,并且将fd指向它。
对于在fd数组中有入口地址的每个文件来说,数组的索引就是文件描述符。通常,数组的第一个元素(索引为0)表示进程的标准输入文件,数组的第二个元素(索引为1)是进程的标准输出文件,数组的第三个元素(索引为2)是进程的标准错误文件)
1. fs_struct
fs_struct 结构描述进程与文件系统的关系
2.1数据结构
我们来深入分析其代码,它的定义在 include/linux/fs_struct.h,
struct fs_struct {
int users;
spinlock_t lock; //保护该结构体的锁
int umask; //默认的文件访问权限
int in_exec;
struct path root, pwd;
};
看一下struct path 结构的定义 :
struct path {
struct vfsmount *mnt;
struct dentry *dentry;
}
可以看到struct path 封装了vfsmount 和dentry;,所以struct path root,pwd包含了当前进程的当前工作目录和根目录以及根目录安装点对象和pwd安装点对象。
3. file_system_type
在Linux中,用file_system_type来描述各种特定文件系统类型,比如ext3。也就是说Linux支持的所有文件系统类型都分别唯一的对应一个file_system_type结构。
3.1 数据结构
它的定义在 include/linux/fs.h中。
struct file_system_type {
......
};
成员说明:
(1) name:文件系统的名字,不能为空;
(2) get_sb:在安装文件系统时,调用此指针所指函数以在磁盘中获取超级块;
(3) kill_sb:卸载文件文件系统时候,调用此指针所指函数以进行一些清理工作;
(4) owner:如果一个文件系统以模块的形式加载到内核,则该字段用来说明哪个模块拥有这个结构。一般为THIS_MODULE;
(5) next:所有的文件系统类型结构形成一个链表,该链表的头指针为全局变量file_systems(struct file_system_type *file_systems)。这个字段指向链表中下一个文件系统类型结构;
(6) fs_supers:同一个文件系统类型下的所有超级块形成一个双联表,这个字段是这个双联表的头结点。超级块之间通过s_instances字段相互链接.
3.2 vfsmount结构体
当文件系统被实际安装时,将有一个vfsmount 结构体在安装点被创建。该结构体用来代表文件系统的实例即代表一个安装点。
vfsmount结构体被定义在 include/linux/mount.h中。vfsmount 结构还保存了在安装时指定的标志信息,该信息存储在mmt_flags中。
MNT_NOSUID:禁止该文件系统的可执行文件设置setuid和setgid标志
MNT_NODEV:禁止访问该文件系统上的设备文件
MNT_NOEXEC:禁止执行该文件系统上的可执行文件
说明:
在管理员安装一些不是很安全的移动设备时,这些标志很有用。
我们来看个图: