文件描述符fd究竟是怎么和file_operations绑定的,fd是来自task_struct里面fd_array数组下标,还是来自fdtable,烦请韦老师能给出具体的函数调用过程。

image

先说答案:
fd来自task_struct里files_struct类型的fdt中fd数组的下标,不是fd_array数组的下标。
但是,一开始时fd数组就是fd_array数组。
看看下面的结构体:

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];
};

提问:

  1. fd_array数组只有32个数组项,但是我们的APP能打开的文件个数超过32,怎么回事?
    答:创建进程时,task_struct里files_struct类型的fdt中fd,指向fd_array;当打开的文件个数超过fd_array时,会重新分配更大的数组,fd指向新的数组。

  2. 所以,我们涉及的都是task_struct里files_struct类型的fdt中fd,不是fd_array

至于fd和file_operations如何绑定,内部过程过于复杂,简单讲讲:

  1. fd会对应task_struct.files->fdt->fd[fd]的file结构体
  2. file结构体里有:file_operations成员
  3. 在哪里设置file结构体的file_operations呢?在内核的一系列的open操作里:
    3.1 发现打开的文件是一个特殊的文件(字符设备节点)时,就会设置file->f_op
    3.2 函数调用过程太复杂,可以看看这个调用过程:
do_sys_open
    do_filp_open
        path_openat
             do_o_path
                vfs_open
                       do_dentry_open
                               f->f_op = fops_get(inode->i_fop);