zoukankan      html  css  js  c++  java
  • Linux文件系统学习(二)之重要数据结构(1)

    转载自:https://blog.csdn.net/wudongxu/article/details/6436894

    《Linux内核设计与实现》

    http://www.ibm.com/developerworks/cn/linux/l-cn-vfs/

    http://www.ibm.com/developerworks/cn/linux/l-linux-filesystem/

    http://www.ibm.com/developerworks/cn/linux/l-cn-read/index.html

    (1)(文件系统类型)file_system_type:

    用于描述具体的文件系统的类型信息,所以被Linux支持的文件系统,都有且仅有一个file_system_type结构而不管它有零个或多个实例被安装到系统中。如ext2,ext3,NFS。

    struct file_system_type {
      const char *name;
      int fs_flags;
    #define FS_REQUIRES_DEV   1 
    #define FS_BINARY_MOUNTDATA 2
    #define FS_HAS_SUBTYPE    4
    #define FS_USERNS_MOUNT   8 /* Can be mounted by userns root */
    #define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */
    #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
      struct dentry *(*mount) (struct file_system_type *, int, 
               const char *, void *);
      void (*kill_sb) (struct super_block *);
      struct module *owner;
      struct file_system_type * next;
      struct hlist_head fs_supers;
    
      struct lock_class_key s_lock_key;
      struct lock_class_key s_umount_key;
      struct lock_class_key s_vfs_rename_key;
      struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];
    
      struct lock_class_key i_lock_key;
      struct lock_class_key i_mutex_key;
      struct lock_class_key i_mutex_dir_key;
    };

    主要结构体成员说明:

    name             文件系统的名字

    fs_flags         文件系统类型标志的bitmap(有6种类型)。

    mount            在mount文件系统时候,会调用该函数创建suber_block,root_inode等相关信息。

    kill_sb          在umount文件系统时候,调用该函数删除suber_block。

    owner            指向拥有这个结构的模块,如果一个文件系统被编译进内核,那么该字段为NULL。

    next             指向向下一个文件系统类型。

    fs_supers        同一种文件类型的超级块形成一个链表,fs_supers是这个链表的头。

    (2)超级块对象(super_block):

    存储一个已安装的文件系统的控制信息(文件系统的状态、文件系统类型、块大小、区块数、索引节点数、脏标志、操作方法),它代表一个已安装的文件系统;每次一个实际的文件系统被安装时,内核会从磁盘的特定位置(磁盘的超级块位置)读取一些控制信息来填充内存中的超级块对象。一个安装实例和一个超级块对象一一对应。超级块通过其结中的一个域s_type记录它所属的文件系统类型。即使安装了两个相同的文件系统(file_system_type一样)也会有两个超级块(磁盘与内存都有两个)。

    struct super_block {
      struct list_head  s_list;   /* Keep this first */
      dev_t     s_dev;    /* search index; _not_ kdev_t */
      unsigned char   s_blocksize_bits;
      unsigned long   s_blocksize;
      loff_t      s_maxbytes; /* Max file size */
      struct file_system_type *s_type;
      const struct super_operations *s_op;
      const struct dquot_operations *dq_op;
      const struct quotactl_ops *s_qcop;
      const struct export_operations *s_export_op;
      unsigned long   s_flags;
      unsigned long   s_magic;
      struct dentry   *s_root;
      struct rw_semaphore s_umount;
      int     s_count;
      atomic_t    s_active;
    #ifdef CONFIG_SECURITY
      void                    *s_security;
    #endif
      const struct xattr_handler **s_xattr;
    
      struct list_head  s_inodes; /* all inodes */
      struct hlist_bl_head  s_anon;   /* anonymous dentries for (nfs) exporting */
    #ifdef CONFIG_SMP
      struct list_head __percpu *s_files;
    #else
      struct list_head  s_files;
    #endif
      struct list_head  s_mounts; /* list of mounts; _not_ for fs use */
      /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
      struct list_head  s_dentry_lru; /* unused dentry lru */
      int     s_nr_dentry_unused; /* # of dentry on lru */
    
      /* s_inode_lru_lock protects s_inode_lru and s_nr_inodes_unused */
      spinlock_t    s_inode_lru_lock ____cacheline_aligned_in_smp;
      struct list_head  s_inode_lru;    /* unused inode lru */
      int     s_nr_inodes_unused; /* # of inodes on lru */
    
      struct block_device *s_bdev;
      struct backing_dev_info *s_bdi;
      struct mtd_info   *s_mtd;
      struct hlist_node s_instances;
      struct quota_info s_dquot;  /* Diskquota specific options */
    
      struct sb_writers s_writers;
    
      char s_id[32];        /* Informational name */
      u8 s_uuid[16];        /* UUID */
    
      void      *s_fs_info; /* Filesystem private info */
      unsigned int    s_max_links;
      fmode_t     s_mode;
      /* Granularity of c/m/atime in ns.
         Cannot be worse than a second */
      u32      s_time_gran;
    
      /*
       * The next field is for VFS *only*. No filesystems have any business
       * even looking at it. You had been warned.
       */
      struct mutex s_vfs_rename_mutex;  /* Kludge */
    
      /*
       * Filesystem subtype.  If non-empty the filesystem type field
       * in /proc/mounts will be "type.subtype"
       */
      char *s_subtype;
    
      /*
       * Saved mount options for lazy filesystems using
       * generic_show_options()
       */
      char __rcu *s_options;
      const struct dentry_operations *s_d_op; /* default d_op for dentries */
    
      /*
       * Saved pool identifier for cleancache (-1 means none)
       */
      int cleancache_poolid;
    
      struct shrinker s_shrink; /* per-sb shrinker handle */
    
      /* Number of inodes with nlink == 0 but still referenced */
      atomic_long_t s_remove_count;
    
      /* Being remounted read-only */
      int s_readonly_remount;
    };
    
      

    这个super_block 数据结构十分的巨大,毕竟是包含一个文件系统的重要信息。对我们来说对这个数据结构全部说明,实际上是没有必要的,只要记住一些关键的成员即可。等待实际的开发过程,如果有涉及到的话,再去重点关注即可。

    s_list                   一个双向循环链表,把系统中所有的文件系统连接起来,一个super_block 在linux的文件系统结构中代表一个文件系统,s_list 包含了linux系统里面所有的文件系统。

    dev                      设备标识符。

    s_blocksize              文件系统块大小

    s_blocksize_bits         大小的位数

    s_maxbytes              最大文件大小

    s_type                   文件系统类型

    s_op                     suber_block 的操作集合,例如new_inode 等。

    s_flags                文件系统的超级块状态。

    s_magic                 每一个超级块的唯一魔术标识。

    s_root            指向文件系统的根目录的dentry(将在下来的文章中说明)结构体。

    s_inodes         所有的这个文件系统的inode结构体都在这个队列上。

    s_id[32]          文件系统的名字

    s_fs_info       文件系统的私有信息指针,这个指针是非常重要的,它实际是指向下层实际文件系统的结构体。

    安装点(vfsmount/mount):当一个文件系统被实际安装,就有一个vfsmount/mount结构体被创建,这个结构体对应一个安装点。与超级块一样(即与超级块是一一对应的),但没有存放在磁盘中。它包括安装点的相关信息,如位置和安装标志等。(早期linux内核版本的安装点只有zfsmount,现在已经将其一拆为二了,具体从哪个版本开始拆题主并没有去查看,题注用的版本是已经拆分完成的)

    vfsmount 结构体在include/linux/mount.h

    struct vfsmount {
      struct dentry *mnt_root;  /* root of the mounted tree */
      struct super_block *mnt_sb; /* pointer to superblock */
      int mnt_flags;
    };

    mount 结构体在fs/mount.h文件里面

    struct mount {
      struct list_head mnt_hash;
      struct mount *mnt_parent;
      struct dentry *mnt_mountpoint;
      struct vfsmount mnt;
    #ifdef CONFIG_SMP
      struct mnt_pcp __percpu *mnt_pcp;
    #else
      int mnt_count;
      int mnt_writers;
    #endif
      struct list_head mnt_mounts;  /* list of children, anchored here */
      struct list_head mnt_child; /* and going through their mnt_child */
      struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
      const char *mnt_devname;  /* Name of device e.g. /dev/dsk/hda1 */
      struct list_head mnt_list;
      struct list_head mnt_expire;  /* link in fs-specific expiry list */
      struct list_head mnt_share; /* circular list of shared mounts */
      struct list_head mnt_slave_list;/* list of slave mounts */
      struct list_head mnt_slave; /* slave list entry */
      struct mount *mnt_master; /* slave is on master->mnt_slave_list */
      struct mnt_namespace *mnt_ns; /* containing namespace */
      struct mountpoint *mnt_mp;  /* where is it mounted */
    #ifdef CONFIG_FSNOTIFY
      struct hlist_head mnt_fsnotify_marks;
      __u32 mnt_fsnotify_mask;
    #endif
      int mnt_id;     /* mount identifier */
      int mnt_group_id;   /* peer group identifier */
      int mnt_expiry_mark;    /* true if marked for expiry */
      int mnt_pinned;
      int mnt_ghosts;
    };

    这两个结构体成员注释里面基本说明清楚了,这里就不在做解释了。这里只做一个说明,就是怎么样通过vfsmount 来获取mount。其实也很简单,就是通过内核提供的container_of来获取,具体代码如下

    static inline struct mount *real_mount(struct vfsmount *mnt)
    {
      return container_of(mnt, struct mount, mnt);
    }

     

  • 相关阅读:
    mysql 中 group_concat()用法
    MySQL行转列与列转行
    mysql中find_in_set()函数的使用(转载)
    多线程中的线程安全关键字
    架构师的特征
    算法复杂度的定义
    1.ArrayList和linkedList区别
    Plsql查询clob类型字段数据
    数据库的特性与隔离级别和spring事务的传播机制和隔离级别
    java中的线程
  • 原文地址:https://www.cnblogs.com/bspp1314/p/9429573.html
Copyright © 2011-2022 走看看