【Linux】Linux内核中的文件管理器files_struct

(1)进程控制块:struct task_struct

       Linux内核中每个进程都存在一个task_struct记录该进程信息,其中一个成员变量files 正是指向管理该进程所有打开文件信息的files_struct类型指针;

(2)文件管理器:struct files_struct

       上面已经说了,struct files_struct结构体管理着进程打开的所有文件,该结构体核心成员如下图所示:

       fd_array[64]为初始文件指针数组,存储文件指针*file,通过该数组便可索引该进程打开过的文件,但需注意该结构体只支持最大64个文件,超过64个文件会进行动态扩展。接下来看fdtfdtab这两个成员,首先来了解struct fdtable这个结构体。

       struct fdtable结构体为文件描述符表,其核心成员如下:

       struct file **fd是一个指向file*的指针,通过fd可以访问fd_array[]存储的所有文件指针。max_fds表示fd_array[]储存的最大文件数。

       回头来看struct files_struct中的fdtab成员与fdt成员,fdtab是内嵌的初始文件描述符表,fdtab.fd指针则指向了struct files_struct中的fd_array[64];fdt成员又指向了fdtab。此时fdt->fd = fd_array,通过fdt->fd[i]即可访问索引为i的文件。

       需要注意的是只有当打开文件数目少于64时,fdt才会指向fdtab。当打开文件数目超过64时,要进行动态扩展,其过程便是令fdt指向新创建的struct fdtable结构体,并将原fd_array[64]的数据拷贝到内存更大的新表。

(3)文件描述符:fd

       fd是一个非负整数,本质上就是一个索引值,同上文fdt->fd[i]中的i

(4)文件对象:struct file

       前面已经提到fd 本质是数组索引,数组元素便是struct file结构体的指针,表征进程打开的文件。其简化结构如下图所示:

      f_path:标识文件名;

      f_inode:指向文件的inode对象,包含文件元数据(大小、权限、时间戳等);

      f_op:文件操作函数表(虚拟函数表);

      f_count:引用计数器,通过get_file()/fput()管理生命周期,当计数归零时调用f_op->release();

     f_pos:当前文件读写位置,f_pos在open的时候会设置成默认值,seek的时候可以更改,从而影响到write/read的位置。

(5) 进程调用open打开文件过程

    当进程调用open("/path/to/file",O_RDONLY)时经过以下几步:

    解析路径:内核通过 目录项缓存(dcache)查找路径对应的dentry,进而找到inode

    创建struct file:分配一个新的file对象,关联到inode,并设置初始偏移量(f_pos=0)。

    分配fd:在current->files->fdt->fd[]中找到一个空闲位置(如 fd=3),存储file*

    返回fd给用户态:用户程序后续通过fd操作文件。

(6) 进程调用read过程

       通过fd找到file*:内核检查current->files->fdt->fd[fd],获取struct file*

      调用文件操作函数:file->f_op->read()

      检查页缓存:如果数据在缓存中(inode->i_mapping),直接拷贝到用户缓冲区。如果不在缓存,触发磁盘I/O,数据读入缓存后再返回。

      更新文件偏移量:file->f_pos += 实际读取的字节数。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值