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);
}

 

原文地址:https://www.cnblogs.com/bspp1314/p/9429573.html