linux内核文件描述符fd、文件索引节点inode、文件对象file关系

文件描述符fd、文件索引节点inode、文件对象file关系

  • 1 VFS对象
    • 1.1 超级块对象
    • 1.2 索引节点对象
    • 1.3 文件对象
    • 1.4 进程描述符
    • 1.5 files_struct
  • 2 如何根据文件描述符fd找到文件?

1 VFS对象

在说fd、inode和file关系之前,我们先了解VFS的几个概念。分别是进程描述符、超级块对象、索引节点和文件对象。

1.1 超级块对象

超级块对象代表一个已安装的文件系统,由super_block结构体表示,定义在文件linux/fs中。

1.2 索引节点对象

索引节点对象代表一个具体文件,由struct inode结构体表示,定义在linux/fs.h中。

1.3 文件对象

文件对象表示一个进程已经打开的文件。由struct file结构体表示,定义在linux/fs.h中。

struct file {
	...
	struct inode		*f_inode;	/* cached value */
	const struct file_operations	*f_op;
	...
};

f_inode指向一个具体文件。

1.4 进程描述符

进程描述符来代表一个进程,由结构体struct task_struct表示,该结构定义在include/linux/sched.h文件中。

struct task_struct {
		...
	/* open file information */
	struct files_struct *files;
	...
};

我们要注意files域,该域指向一个进程打开的所有文件。

1.5 files_struct

files_struct表示一个进程打开的所有文件,files_struct结构体定义在文件linux/fdtable.h中。该结构体由进程描述符中的files域指向。所有与每个进程打开的文件及文件描述符都包含在其中,其结构体描述如下:

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;
	unsigned int next_fd;
	unsigned long close_on_exec_init[1];
	unsigned long open_fds_init[1];
	unsigned long full_fds_bits_init[1];
	struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

struct fdtable结构体如下:

struct fdtable {
	unsigned int max_fds;
	struct file __rcu **fd;      /* current fd array */
	unsigned long *close_on_exec;
	unsigned long *open_fds;
	unsigned long *full_fds_bits;
	struct rcu_head rcu;
};

fd域指向的就是进程打开的文件,它实际是个数组,fd数组指针指向已打开的文件对象链表,默认情况下,指向fd_array数组,NR_OPEN_DEFAULT是个定值,当一个进程打开的文件对象超过NR_OPEN_DEFAULT时,内核将分配一个新数组,并且用fd指针指向它。

文件描述符fd就是索引值,在fd数组中找到文件对象。

2 如何根据文件描述符fd找到文件?

我们用write的系统调用来分析如何找到文件的,
首先会文件文件描述符fd获取结构体类型struct fd

struct fd f = fdget_pos(fd);


struct fd {
	struct file *file;
	unsigned int flags;
};

fdget_pos函数中会调用很多很函数,它会先用当前进程current找到files域,然后在files中找到struct fdtable类型指针fdt,在fdt里面找到指向文件对象的fd数组,fd数组根据文件描述符fd(索引)找到进程打开的文件对象,最后返回。

fdget_pos返回的是一个struct fd结构体,这个结构体里面就是我们找到的文件对象,后面就可以根据这个文件对象找到文件的索引节点。

注意:文件对象代表的是进程打开的文件,索引节点代表的是真正的文件,可能有多个不同进程的文件对象指向同一个索引节点

你可能感兴趣的:(Linux内核设计与实现,linux内核)