zoukankan      html  css  js  c++  java
  • VFS四大对象之四-struct file

    继上一篇文章:

    http://www.cnblogs.com/linhaostudy/p/7428971.html

    四、file结构体

    文件对象:注意文件对象描述的是进程已经打开的文件。因为一个文件可以被多个进程打开,所以一个文件可以存在多个文件对象。但是由于文件是唯一的,那么inode就是唯一的,目录项也是定的!

    进程其实是通过文件描述符来操作文件的,注意每个文件都有一个32位的数字来表示下一个读写的字节位置,这个数字叫做文件位置。

    565 struct file {
    566         struct list_head        f_list;
    567         struct dentry           *f_dentry;
    568         struct vfsmount         *f_vfsmnt;
    569         struct file_operations  *f_op;
    570         atomic_t                f_count;
    571         unsigned int            f_flags;
    572         mode_t                  f_mode;
    573         loff_t                  f_pos;
    574         unsigned long           f_reada, f_ramax, f_raend, f_ralen, f_rawin;
    575         struct fown_struct      f_owner;
    576         unsigned int            f_uid, f_gid;
    577         int                     f_error;
    578 
    579         size_t                  f_maxcount;
    580         unsigned long           f_version;
    581 
    582         /* needed for tty driver, and maybe others */
    583         void                    *private_data;
    584 
    585         /* preallocated helper kiobuf to speedup O_DIRECT */
    586         struct kiobuf           *f_iobuf;
    587         long                    f_iobuf_lock;
    588 };

    f_list:所有的打开的文件形成的链表!注意一个文件系统所有的打开的文件都通过这个链接到super_block中的s_files链表中!

    f_dentry:与该文件相关的dentry

    f_vfsmnt:该文件在这个文件系统中的安装点

    f_op:文件操作,当进程打开文件的时候,这个文件的关联inode中的i_fop文件操作会初始化这个f_op字段

    f_count:引用计数

    f_flags:打开文件时候指定的标识

    f_mode:文件的访问模式

    f_pos:目前文件的相对开头的偏移

    unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin:预读标志、要预读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数

    f_owner:记录一个进程ID,以及当某些事发送的时候发送给该ID进程的信号

    f_uid:用户ID

    f_gid:组ID

    f_error:写操作错误码

    f_version:版本号,当f_pos改变时候,version递增

    private_data:私有数据( 文件系统和驱动程序使用 )

    重点解释一些重要字段

    首先,f_flags、f_mode和f_pos代表的是这个进程当前操作这个文件的控制信息。这个非常重要,因为对于一个文件,可以被多个进程同时打开,那么对于每个进程来说,操作这个文件是异步的,所以这个三个字段就很重要了。

    第二:对于引用计数f_count,当我们关闭一个进程的某一个文件描述符时候,其实并不是真正的关闭文件,仅仅是将f_count减一,当f_count=0时候,才会真的去关闭它。对于dup,fork这些操作来说,都会使得f_count增加,具体的细节,以后再说。

    第三:f_op也是很重要的!是涉及到所有的文件的操作结构体。例如:用户使用read,最终都会调用file_operations中的读操作,而file_operations结构体是对于不同的文件系统不一定相同。里面一个重要的操作函数式release函数,当用户执行close时候,其实在内核中是执行release函数,这个函数仅仅将f_count减一,这也就解释了上面说的,用户close一个文件其实是将f_count减一。只有引用计数减到0才关闭文件。

    注意:对于“正在使用”和“未使用”的文件对象分别使用一个双向链表进行管理。

    注意上面的file只是对一个文件而言,对于一个进程(用户)来说,可以同时处理多个文件,所以需要另一个结构来管理所有的files!

    即:用户打开文件表--->files_struct

    172 struct files_struct {
    173         atomic_t count;
    174         rwlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */
    175         int max_fds;
    176         int max_fdset;
    177         int next_fd;
    178         struct file ** fd;      /* current fd array */
    179         fd_set *close_on_exec;
    180         fd_set *open_fds;
    181         fd_set close_on_exec_init;
    182         fd_set open_fds_init;
    183         struct file * fd_array[NR_OPEN_DEFAULT];
    184 };

     解释一些字段:

    count:引用计数

    file_lock:锁,保护下面的字段

    max_fds:当前文件对象的最大的数量

    max_fdset:文件描述符最大数

    next_fd:已分配的最大的文件描述符+1

    fd:指向文件对象指针数组的指针,一般就是指向最后一个字段fd_arrray,当文件数超过NR_OPEN_DEFAULT时候,就会重新分配一个数组,然后指向这个新的数组指针!

    close_on_exec:执行exec()时候需要关闭的文件描述符

    open_fds:指向打开的文件描述符的指针

    close_on_exec_init:执行exec()时候需要关闭的文件描述符初始化值

    open_fds_init:文件描述符初值集合

    fd_array:文件对象指针的初始化数组

    注意上面的file和files_struct记录的是与进程相关的文件的信息,但是对于进程本身来说,自身的一些信息用什么表示,这里就涉及到fs_struct结构体。

      5 struct fs_struct {
      6         atomic_t count;
      7         rwlock_t lock;
      8         int umask;
      9         struct dentry * root, * pwd, * altroot;
     10         struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
     11 };

     解释一些字段:

    count:引用计数

    lock:保护锁

    umask:打开文件时候默认的文件访问权限

    root:进程的根目录

    pwd:进程当前的执行目录

    altroot:用户设置的替换根目录

    注意:实际运行时,这三个目录不一定都在同一个文件系统中。例如,进程的根目录通常是安装于“/”节点上的ext文件系统,而当前工作目录可能是安装于/etc的一个文件系统,替换根目录也可以不同文件系统中。

    rootmnt,pwdmnt,altrootmnt:对应于上面三个的安装点。

  • 相关阅读:
    SCCM2012分发脚本
    MPIO配置
    创建快捷方式,修改注册表
    常用口语 一
    3463工厂频道预置方法
    xargs 主要用于不支持管道的shell命令*****
    RDA DEBUG
    linux shell 实例1
    MSD3458开发资料
    MSD6A628开发资料与技术支持
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/7459017.html
Copyright © 2011-2022 走看看