每个进程都有自己的根目录和当前工作目录,内核使用struct fs_struct来记录这些信息,进程描述符的fs字段便是指向该进程的fs_struct结构。
fs_struct 定义于 include/linux/fs_struct.h 。
struct fs_struct {
int users;
spinlock_t lock;
seqcount_t seq;
int umask;
int in_exec;
struct path root, pwd;
};
除了根目录和当前工作目录,进程还需要记录自己打开的文件。进程已经打开的所有文件使用struct files_struct来记录,进程描述符的files字段便指向该进程的files_struct结构。
files_struct 定义于 include/linux/fdtable.h.
struct files_struct {
/*
* read mostly part
*/
atomic_t count;
bool resize_in_progress;
wait_queue_head_t resize_wait;
struct fdtable __rcu *fdt;
struct fdtable fdtab;
/*
* written part on a separate cache line in SMP
*/
spinlock_t file_lock ____cacheline_aligned_in_smp;
int next_fd;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};
由于NR_OPEN_DEFAULT在x86结构下的定义为32,在ia64结构下的定义为64,所以说,fd_array最多只能存储32或64个文件对象,远远小于进程被允许打开的最大文件数NR_OPEN, 如果超过了NR_OPEN_DEFAULT, 多出来的文件对象将如何存储呢?
显然,内核必须分配新的存储空间存放这些文件对象的指针。旧版本的内核中,struct file_struct中有一个fd字段,指向文件对象的指针数组。通常fd指向fd_array,如果进程打开的文件数目多于32个,内核就分配一个新的更大的文件对象的指针数组,并将其地址存放在fd字段中,这个数组所包含的元素数目存放在max_fds字段。
新版本的内核将fd,max_fds以及其他几个相关字段组织在一起,增加一个新的独立数据结构struct fdtable,成为文件描述符表,其主要数据结构定义如下所示:
fdtable 定义于 include/linux/fdtable.h 。
struct fdtable {
unsigned int max_fds;
struct file __rcu **fd; /* current fd array */
unsigned long *close_on_exec;
unsigned long *open_fds;
struct rcu_head rcu;
};
原文链接:https://mudongliang.github.io/2015/10/25/linuxvfs-6.html