VFS粗略总结

参考以下两篇文章

http://blog.csdn.net/yuzhihui_no1/article/details/51272563

http://blog.csdn.net/shanshanpt/article/details/39026915

VFS虚拟文件系统,是对于用户的接口,它允许硬盘中有多种文件系统,而VFS屏蔽了底层的差异,使得对于上层看来底层是一样的。

在Linux的task_struct中,里面和文件相关的有两个指针,先说下其中的files,它指向struct file_struct结构体,这个结构体是每个进程独自拥有的。下面是相关的一些内容

struct files_struct {

atomic_t count; /* 共享该表的进程数 */

rwlock_t file_lock; /* 保护以下的所有域,以免在tsk->alloc_lock中的嵌套*/

int max_fds; /*当前文件对象的最大数*/

int max_fdset; /*当前文件描述符的最大数*/

int next_fd; /*已分配的文件描述符加1*/

struct file ** fd; /* 指向文件对象指针数组的指针 */

fd_set *close_on_exec; /*指向执行exec( )时需要关闭的文件描述符*/

fd_set *open_fds; /*指向打开文件描述符的指针*/

fd_set close_on_exec_init;/* 执行exec( )时需要关闭的文件描述符的初 值集合*/

        fd_set open_fds_init; /*文件描述符的初值集合*/

struct file * fd_array[32];/* 文件对象指针的初始化数组*/

};

要解释的是其中的struct file **fd,fd也是指向一张表,表中存放的是指针,指向struct file,它初始化的时候是等于struct file fd_array[32]中的fd_array,这个是表只能存下32个struct file指针,当打开的文件多于32的时候,内核会将fd指向另一张表,并且将原来表中的内容复制过去。并且更新max_fds。我们每次用open打开一个文件,返回一个整数,就是作为fd的偏移量,去查找相关的struct file指针。open_fds是指向打开的文件描述符,它是指向fd_set结构的(fd_set是位,里面的每一位代表一个数字)。它初始化的时候是指向open_fds_init,比如0,1,2这三个一开始就是打开的描述符,fd_array[0]是指向标准输出的指针。之后每次打开一个文件内核就会将文件描述符添加到里面open_fds指向的fd_set数据结构。另外关于select中描述符最大是1024,可以看出fd_set这个数据结构本身受限制。


在讲解下面的几个结构体之前,先说下List_head结构体,内核中大量用到这个结构体,详细参考这篇文章http://blog.csdn.net/u013904227/article/details/50931540

内核中将节点连接成链表,是在节点中存放struct list_head{ struct list_head *next,*pre} 这样一个结构体。通过这个结构体将节点连接成双向链表。之后根据这个链表中的这个节点可以找到此节点所在的结构体。

索引节点Inode:inode是保存在磁盘中,它存放的内容的文件的一些元数据,如文件大小,访问时间,用户标识符,设备标识符,链接的数量,以及指向实际的数据块的指针。inode在硬盘中的数量是一定的。操作系统会把硬盘中的inode分为使用和未使用保存在内存中。一个文件对应一个inode,一个Inode也只标记一个文件,文件的名字是给用户使用的,在操作系统的内部用的是Inode。

struct inode {
441         struct list_head        i_hash;
442         struct list_head        i_list;
443         struct list_head        i_dentry;
444         
445         struct list_head        i_dirty_buffers;
446         struct list_head        i_dirty_data_buffers;
447 
448         unsigned long           i_ino;
449         atomic_t                i_count;
450         kdev_t                  i_dev;
451         umode_t                 i_mode;
452         unsigned int            i_nlink;
453         uid_t                   i_uid;
454         gid_t                   i_gid;
455         kdev_t                  i_rdev;
456         loff_t                  i_size;
457         time_t                  i_atime;
458         time_t                  i_mtime;
459         time_t                  i_ctime;
460         unsigned int            i_blkbits;
461         unsigned long           i_blksize;
462         unsigned long           i_blocks;
463         unsigned long           i_version;
464         unsigned short          i_bytes;
465         struct semaphore        i_sem;
466         struct rw_semaphore     i_alloc_sem;
467         struct semaphore        i_zombie;
468         struct inode_operations *i_op;
469         struct file_operations  *i_fop; /* former ->i_op->default_file_ops */
470         struct super_block      *i_sb;
471         wait_queue_head_t       i_wait;
472         struct file_lock        *i_flock;
473         struct address_space    *i_mapping;
474         struct address_space    i_data;
475         struct dquot            *i_dquot[MAXQUOTAS];
476         /* These three should probably be a union */
477         struct list_head        i_devices;
478         struct pipe_inode_info  *i_pipe;
479         struct block_device     *i_bdev;
480         struct char_device      *i_cdev;
481 
482         unsigned long           i_dnotify_mask; /* Directory notify events */
483         struct dnotify_struct   *i_dnotify; /* for directory notifications */
484 
485         unsigned long           i_state;
486 
487         unsigned int            i_flags;
488         unsigned char           i_sock;
489 
490         atomic_t                i_writecount;
491         unsigned int            i_attr_flags;
492         __u32                   i_generation;
493         union {
494                 struct minix_inode_info         minix_i;
495                 struct ext2_inode_info          ext2_i;
496                 struct ext3_inode_info          ext3_i;
497                 struct hpfs_inode_info          hpfs_i;
498                 struct ntfs_inode_info          ntfs_i;
499                 struct msdos_inode_info         msdos_i;
500                 struct umsdos_inode_info        umsdos_i;
501                 struct iso_inode_info           isofs_i;
502                 struct nfs_inode_info           nfs_i;
503                 struct sysv_inode_info          sysv_i;
504                 struct affs_inode_info          affs_i;
505                 struct ufs_inode_info           ufs_i;
506                 struct efs_inode_info           efs_i;
507                 struct romfs_inode_info         romfs_i;
508                 struct shmem_inode_info         shmem_i;
509                 struct coda_inode_info          coda_i;
510                 struct smb_inode_info           smbfs_i;
511                 struct hfs_inode_info           hfs_i;
512                 struct adfs_inode_info          adfs_i;
513                 struct qnx4_inode_info          qnx4_i;
514                 struct reiserfs_inode_info      reiserfs_i;
515                 struct bfs_inode_info           bfs_i;
516                 struct udf_inode_info           udf_i;
517                 struct ncp_inode_info           ncpfs_i;
518                 struct proc_inode_info          proc_i;
519                 struct socket                   socket_i;
520                 struct usbdev_inode_info        usbdev_i;
521                 struct jffs2_inode_info         jffs2_i;
522                 void                            *generic_ip;
523         } u;
524 };</span></pre><span style="font-size:14px"><br>

i_dentry:指向目录项链表的指针。对于一个inode可以对应对个dentry(dentry下面会说),也就是硬链接-----一个实际的文件可以连接到其他的文件中去。每一个文件都对应一个dentry。这个指针可以将相同的inode的dentry连接起来。Linux里面有查看一个文件所以的硬链接,就是和这个有关。    

i_hash是为了加快正在使用的Inode的查找效率,将正在使用的inode放在哈希表中,这个是开哈希表。根据不同的Inode值映射到数组上面,在将哈希值相等的inode通过i_hash连接起来。

struct dentry 目录项结构体  ,目录项值存在内存中,为了提高查找文件的性能设计的。注意在VFS里面无论是文件还是目录,都看成文件。d_inode指向目录的inode,下面的d_hash和上面的inode的i_hash差不多,也是开哈希表。d_subdirs,目录中的子项都要链接到这个d_subdirs的链表中,子项是通过d_child链接到d_subdirs。



struct file结构体:

structfile

{

struct list_head f_list; /*所有打开的文件形成一个链表*/

struct dentry *f_dentry; /*指向相关目录项的指针*/

struct vfsmount *f_vfsmnt; /*指向VFS安装点的指针*/

struct file_operations *f_op; /*指向文件操作表的指针*/

mode_t f_mode; /*文件的打开模式*/

loff_t f_pos; /*文件的当前位置*/

unsigned short f_flags; /*打开文件时所指定的标志*/


unsigned short f_count; /*使用该结构的进程数*/

unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;

/*预读标志、要预读的最多页面数、上次预读后的文件指针、预读的字节数以及

预读的页面数*/

int f_owner; /* 通过信号进行异步I/O数据的传送*/

unsigned int f_uid, f_gid; /*用户的UID和GID*/

int f_error; /*网络写操作的错误码*/

unsigned long f_version; /*版本号*/

void *private_data; /* tty驱动程序所需 */

};

这个表示操作系统维护的,所有进程共享的。每次打开一个文件都会建立这个结构的(即使在一个进程中重复打开一个文件也会重新建立一个此文件的struct file的结构的),f_list使得这些结构连接起来。f_dentry指向此文件对应的f_dentry,一个文件在内存中会对应一个dentry的,这个下面会讲。f_op是指向文件操作表的指针,文件操作表里面存放的是read,write等等和读取文件的系统调用,文件存放在不同的文件系统中,这个变量指向的表也不一样。f_count是引用计数,当f_count为0,那么这个文件才会被关闭。f_pos是读写的位置。当一个进程,fork出子进程后,子进程持有父进程struct file_struct的一块拷贝,并且持有fd指向的文件描述符表的拷贝。这样父进程对文件的位置的操作(例如read,write)对于子进程来说也是可见的。

通过上面的我们用open打开一个文件的操作是这样子的,open返回一个文件描述符,通过文件描述符找到struct file,在这个里面找到dentry,根据计算的hash值,在i_hash链接成的表中找到次节点,在根据节点中的inode值,找到对应的block,如果block中存放的是数据,那就是我们要找到的文件,如果存放的是子项和inode的映射,那么继续往下找,知道找到文件为止。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值