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:对应于上面三个的安装点。

  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/7459017.html
Copyright © 2011-2022 走看看