linux句柄存储分析

当用户空间程序调用open打开文件,或调用socket创建一个套接字时,都会返回一个int类型的句柄,这个句柄在内核中是怎么存储的,怎么根据句柄找到相应的文件对象或套接字对象呢,这篇文章来分析下这块内容。

进程对象task_struct中的files用来保存此类信息,其定义如下:

/*

 * Open file table structure

 */

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

};

 句柄相关的大部分信息,保存在files_struct的fdt中,下面是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;

};

max_fds       是指当前最多能保存多少个句柄

fd                  如果文件句柄为3,则fd[3]保存了与文件相关的file指针对象

open_fds      从最低位开始,某位为1,则表示相应位置句柄已被占用

full_fds_bits  用来表示open_fds有多少个long型缓存区

用表格来对上面几个字段,进行下说明:

序号 next_fd max_fds full_fds_bits open_fds
1 4 64 0 0xf
2 5 64 0 0x1f
3 6 64 0 0x3f
4 64 64 1 0xffffffffffffffff
5 65 128 1 0x1,ffffffffffffffff
6 66 128 1 0x3,ffffffffffffffff
7 127 128 1 0x7fffffffffffffff,ffffffffffffffff
8 128 128 3 0xffffffffffffffff,ffffffffffffffff
9 129 256 3 0x1,ffffffffffffffff,ffffffffffffffff

表格中的next_fd是files_struct中的字段,为下一个可用的句柄,从0开始计数。next_fd只是起辅助作用,句柄是否可用,以open_fds中的数据为准;

表格中的第一行,open_fds为0xf,对应的二进制表示为1111b,表示前4个句柄已被占用,下一个可用的句柄(next_fd)为4;

max_fds表示当前最多可保存多少个句柄,如缓存区被占满后,会调用expand_files进行扩展。默认情况下open_fds指向保有1个long类型长度的缓存区,最多保存64个句柄;扩展后open_fds指向有2个long类型长度的缓存区,可保存128个句柄;再次扩展后,则有4个long类型长度,保存256个句柄。

full_fds_bits用来表示open_fds的前多少个long类型缓存区被用完,用来辅助快速查找空闲的句柄位置。前3行full_fds_bits为0,表示open_fds第1个long缓存区还有空闲位置;第4到7行,full_fds_bits为1,表示open_fds第1个long缓存区(低64位)被用完;最后两行,full_fds_bits为3(二进制为11b),表示open_fds前两个long缓存区(低128位)被占用完。

总结一下:

文件或套接字,在内核中都有一个file对象与之一一对应,通过查找open_fds,获取下一个可用的句柄x,fdtable->fd[x]保存file对象的指针。

你可能感兴趣的:(网络,linux,内核)