<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《Linux內(nèi)核設計與實現(xiàn)》讀書筆記(十三)- 虛擬文件系統(tǒng)

      虛擬文件系統(tǒng)(VFS)是linux內(nèi)核和具體I/O設備之間的封裝的一層共通訪問接口,通過這層接口,linux內(nèi)核可以以同一的方式訪問各種I/O設備。

      虛擬文件系統(tǒng)本身是linux內(nèi)核的一部分,是純軟件的東西,并不需要任何硬件的支持。

       

      主要內(nèi)容:

      • 虛擬文件系統(tǒng)的作用
      • 虛擬文件系統(tǒng)的4個主要對象
      • 文件系統(tǒng)相關的數(shù)據(jù)結構
      • 進程相關的數(shù)據(jù)結構
      • 小結

       

       

      1. 虛擬文件系統(tǒng)的作用

      虛擬文件系統(tǒng)(VFS)是linux內(nèi)核和存儲設備之間的抽象層,主要有以下好處。

      - 簡化了應用程序的開發(fā):應用通過統(tǒng)一的系統(tǒng)調(diào)用訪問各種存儲介質(zhì)

      - 簡化了新文件系統(tǒng)加入內(nèi)核的過程:新文件系統(tǒng)只要實現(xiàn)VFS的各個接口即可,不需要修改內(nèi)核部分

       

      2. 虛擬文件系統(tǒng)的4個主要對象

      虛擬文件中的4個主要對象,具體每個對象的含義參見如下的詳細介紹。

       

      2.1 超級塊

      超級塊(super_block)主要存儲文件系統(tǒng)相關的信息,這是個針對文件系統(tǒng)級別的概念。

      它一般存儲在磁盤的特定扇區(qū)中,但是對于那些基于內(nèi)存的文件系統(tǒng)(比如proc,sysfs),超級塊是在使用時創(chuàng)建在內(nèi)存中的。

       

      超級塊的定義在:<linux/fs.h>

      /* 
       * 超級塊結構中定義的字段非常多,
       * 這里只介紹一些重要的屬性
       */
      struct super_block {
          struct list_head    s_list;               /* 指向所有超級塊的鏈表 */
          const struct super_operations    *s_op; /* 超級塊方法 */
          struct dentry        *s_root;           /* 目錄掛載點 */
          struct mutex        s_lock;            /* 超級塊信號量 */
          int            s_count;                   /* 超級塊引用計數(shù) */
      
          struct list_head    s_inodes;           /* inode鏈表 */
          struct mtd_info        *s_mtd;            /* 存儲磁盤信息 */
          fmode_t            s_mode;                /* 安裝權限 */
      };
      
      /*
       * 其中的 s_op 中定義了超級塊的操作方法
       * 這里只介紹一些相對重要的函數(shù)
       */
      struct super_operations {
             struct inode *(*alloc_inode)(struct super_block *sb); /* 創(chuàng)建和初始化一個索引節(jié)點對象 */
          void (*destroy_inode)(struct inode *);                /* 釋放給定的索引節(jié)點 */
      
             void (*dirty_inode) (struct inode *);                 /* VFS在索引節(jié)點被修改時會調(diào)用這個函數(shù) */
          int (*write_inode) (struct inode *, int);             /* 將索引節(jié)點寫入磁盤,wait表示寫操作是否需要同步 */
          void (*drop_inode) (struct inode *);                  /* 最后一個指向索引節(jié)點的引用被刪除后,VFS會調(diào)用這個函數(shù) */
          void (*delete_inode) (struct inode *);                /* 從磁盤上刪除指定的索引節(jié)點 */
          void (*put_super) (struct super_block *);             /* 卸載文件系統(tǒng)時由VFS調(diào)用,用來釋放超級塊 */
          void (*write_super) (struct super_block *);           /* 用給定的超級塊更新磁盤上的超級塊 */
          int (*sync_fs)(struct super_block *sb, int wait);     /* 使文件系統(tǒng)中的數(shù)據(jù)與磁盤上的數(shù)據(jù)同步 */
          int (*statfs) (struct dentry *, struct kstatfs *);    /* VFS調(diào)用該函數(shù)獲取文件系統(tǒng)狀態(tài) */
          int (*remount_fs) (struct super_block *, int *, char *); /* 指定新的安裝選項重新安裝文件系統(tǒng)時,VFS會調(diào)用該函數(shù) */
          void (*clear_inode) (struct inode *);                 /* VFS調(diào)用該函數(shù)釋放索引節(jié)點,并清空包含相關數(shù)據(jù)的所有頁面 */
          void (*umount_begin) (struct super_block *);          /* VFS調(diào)用該函數(shù)中斷安裝操作 */
      };

       

      2.2 索引節(jié)點

      索引節(jié)點是VFS中的核心概念,它包含內(nèi)核在操作文件或目錄時需要的全部信息。

      一個索引節(jié)點代表文件系統(tǒng)中的一個文件(這里的文件不僅是指我們平時所認為的普通的文件,還包括目錄,特殊設備文件等等)。

      索引節(jié)點和超級塊一樣是實際存儲在磁盤上的,當被應用程序訪問到時才會在內(nèi)存中創(chuàng)建。

       

      索引節(jié)點定義在:<linux/fs.h>

      /* 
       * 索引節(jié)點結構中定義的字段非常多,
       * 這里只介紹一些重要的屬性
       */
      struct inode {
          struct hlist_node    i_hash;     /* 散列表,用于快速查找inode */
          struct list_head    i_list;        /* 索引節(jié)點鏈表 */
          struct list_head    i_sb_list;  /* 超級塊鏈表超級塊  */
          struct list_head    i_dentry;   /* 目錄項鏈表 */
          unsigned long        i_ino;      /* 節(jié)點號 */
          atomic_t        i_count;        /* 引用計數(shù) */
          unsigned int        i_nlink;    /* 硬鏈接數(shù) */
          uid_t            i_uid;          /* 使用者id */
          gid_t            i_gid;          /* 使用組id */
          struct timespec        i_atime;    /* 最后訪問時間 */
          struct timespec        i_mtime;    /* 最后修改時間 */
          struct timespec        i_ctime;    /* 最后改變時間 */
          const struct inode_operations    *i_op;  /* 索引節(jié)點操作函數(shù) */
          const struct file_operations    *i_fop;    /* 缺省的索引節(jié)點操作 */
          struct super_block    *i_sb;              /* 相關的超級塊 */
          struct address_space    *i_mapping;     /* 相關的地址映射 */
          struct address_space    i_data;         /* 設備地址映射 */
          unsigned int        i_flags;            /* 文件系統(tǒng)標志 */
          void            *i_private;             /* fs 私有指針 */
      };
      
      /*
       * 其中的 i_op 中定義了索引節(jié)點的操作方法
       * 這里只介紹一些相對重要的函數(shù)
       */
      struct inode_operations {
          /* 為dentry對象創(chuàng)造一個新的索引節(jié)點 */
          int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
          /* 在特定文件夾中尋找索引節(jié)點,該索引節(jié)點要對應于dentry中給出的文件名 */
          struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
          /* 創(chuàng)建硬鏈接 */
          int (*link) (struct dentry *,struct inode *,struct dentry *);
          /* 從一個符號鏈接查找它指向的索引節(jié)點 */
          void * (*follow_link) (struct dentry *, struct nameidata *);
          /* 在 follow_link調(diào)用之后,該函數(shù)由VFS調(diào)用進行清除工作 */
          void (*put_link) (struct dentry *, struct nameidata *, void *);
          /* 該函數(shù)由VFS調(diào)用,用于修改文件的大小 */
          void (*truncate) (struct inode *);
      };

       

      2.3 目錄項

      和超級塊和索引節(jié)點不同,目錄項并不是實際存在于磁盤上的。

      在使用的時候在內(nèi)存中創(chuàng)建目錄項對象,其實通過索引節(jié)點已經(jīng)可以定位到指定的文件,

      但是索引節(jié)點對象的屬性非常多,在查找,比較文件時,直接用索引節(jié)點效率不高,所以引入了目錄項的概念。

       

      路徑中的每個部分都是一個目錄項,比如路徑: /mnt/cdrom/foo/bar 其中包含5個目錄項,/ mnt cdrom foo bar

       

      每個目錄項對象都有3種狀態(tài):被使用,未使用和負狀態(tài)

      - 被使用:對應一個有效的索引節(jié)點,并且該對象由一個或多個使用者

      - 未使用:對應一個有效的索引節(jié)點,但是VFS當前并沒有使用這個目錄項

      - 負狀態(tài):沒有對應的有效索引節(jié)點(可能索引節(jié)點被刪除或者路徑不存在了)

       

      目錄項的目的就是提高文件查找,比較的效率,所以訪問過的目錄項都會緩存在slab中。

      slab中緩存的名稱一般就是 dentry,可以通過如下命令查看:

      [wangyubin@localhost kernel]$ sudo cat /proc/slabinfo | grep dentry
      dentry            212545 212625    192   21    1 : tunables    0    0    0 : slabdata  10125  10125      0

       

      目錄項定義在:<linux/dcache.h>

      /* 目錄項對象結構 */
      struct dentry {
          atomic_t d_count;       /* 使用計數(shù) */
          unsigned int d_flags;   /* 目錄項標識 */
          spinlock_t d_lock;        /* 單目錄項鎖 */
          int d_mounted;          /* 是否登錄點的目錄項 */
          struct inode *d_inode;    /* 相關聯(lián)的索引節(jié)點 */
          struct hlist_node d_hash;    /* 散列表 */
          struct dentry *d_parent;    /* 父目錄的目錄項對象 */
          struct qstr d_name;         /* 目錄項名稱 */
          struct list_head d_lru;        /* 未使用的鏈表 */
          /*
           * d_child and d_rcu can share memory
           */
          union {
              struct list_head d_child;    /* child of parent list */
               struct rcu_head d_rcu;
          } d_u;
          struct list_head d_subdirs;    /* 子目錄鏈表 */
          struct list_head d_alias;    /* 索引節(jié)點別名鏈表 */
          unsigned long d_time;        /* 重置時間 */
          const struct dentry_operations *d_op; /* 目錄項操作相關函數(shù) */
          struct super_block *d_sb;    /* 文件的超級塊 */
          void *d_fsdata;            /* 文件系統(tǒng)特有數(shù)據(jù) */
      
          unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* 短文件名 */
      };
      
      /* 目錄項相關操作函數(shù) */
      struct dentry_operations {
          /* 該函數(shù)判斷目錄項對象是否有效。VFS準備從dcache中使用一個目錄項時會調(diào)用這個函數(shù) */
          int (*d_revalidate)(struct dentry *, struct nameidata *);
          /* 為目錄項對象生成hash值 */
          int (*d_hash) (struct dentry *, struct qstr *);
          /* 比較 qstr 類型的2個文件名 */
          int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
          /* 當目錄項對象的 d_count 為0時,VFS調(diào)用這個函數(shù) */
          int (*d_delete)(struct dentry *);
          /* 當目錄項對象將要被釋放時,VFS調(diào)用該函數(shù) */
          void (*d_release)(struct dentry *);
          /* 當目錄項對象丟失其索引節(jié)點時(也就是磁盤索引節(jié)點被刪除了),VFS會調(diào)用該函數(shù) */
          void (*d_iput)(struct dentry *, struct inode *);
          char *(*d_dname)(struct dentry *, char *, int);
      };

       

      2.4 文件對象

      文件對象表示進程已打開的文件,從用戶角度來看,我們在代碼中操作的就是一個文件對象。

      文件對象反過來指向一個目錄項對象(目錄項反過來指向一個索引節(jié)點)

      其實只有目錄項對象才表示一個已打開的實際文件,雖然一個文件對應的文件對象不是唯一的,但其對應的索引節(jié)點和目錄項對象卻是唯一的。

       

      文件對象的定義在: <linux/fs.h>

      /* 
       * 文件對象結構中定義的字段非常多,
       * 這里只介紹一些重要的屬性
       */
      struct file {
          union {
              struct list_head    fu_list;    /* 文件對象鏈表 */
              struct rcu_head     fu_rcuhead; /* 釋放之后的RCU鏈表 */
          } f_u;
          struct path        f_path;             /* 包含的目錄項 */
          const struct file_operations    *f_op; /* 文件操作函數(shù) */
          atomic_long_t        f_count;        /* 文件對象引用計數(shù) */
      };
      
      /*
       * 其中的 f_op 中定義了文件對象的操作方法
       * 這里只介紹一些相對重要的函數(shù)
       */
      struct file_operations {
          /* 用于更新偏移量指針,由系統(tǒng)調(diào)用lleek()調(diào)用它 */
          loff_t (*llseek) (struct file *, loff_t, int);
          /* 由系統(tǒng)調(diào)用read()調(diào)用它 */
          ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
          /* 由系統(tǒng)調(diào)用write()調(diào)用它 */
          ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
          /* 由系統(tǒng)調(diào)用 aio_read() 調(diào)用它 */
          ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
          /* 由系統(tǒng)調(diào)用 aio_write() 調(diào)用它 */
          ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
          /* 將給定文件映射到指定的地址空間上,由系統(tǒng)調(diào)用 mmap 調(diào)用它 */
          int (*mmap) (struct file *, struct vm_area_struct *);
          /* 創(chuàng)建一個新的文件對象,并將它和相應的索引節(jié)點對象關聯(lián)起來 */
          int (*open) (struct inode *, struct file *);
          /* 當已打開文件的引用計數(shù)減少時,VFS調(diào)用該函數(shù) */
          int (*flush) (struct file *, fl_owner_t id);
      };

       

      2.5 四個對象之間關系圖

      上面分別介紹了4種對象分別的屬性和方法,下面用圖來展示這4個對象的和VFS之間關系以及4個對象之間的關系。

      (這個圖是根據(jù)我自己的理解畫出來的,如果由錯誤請幫忙指出,謝謝!)

      VFS-4-objs

       

      VFS-4-objs-2

       

      3. 文件系統(tǒng)相關的數(shù)據(jù)結構

      處理上面4個主要的對象之外,VFS中還有2個專門針對文件系統(tǒng)的2個對象,

      - struct file_system_type: 用來描述文件系統(tǒng)的類型(比如ext3,ntfs等等)

      - struct vfsmount        : 描述一個安裝文件系統(tǒng)的實例

       

      file_system_type 結構體位于:<linux/fs.h>

      struct file_system_type {
          const char *name;   /* 文件系統(tǒng)名稱 */
          int fs_flags;       /* 文件系統(tǒng)類型標志 */
          /* 從磁盤中讀取超級塊,并且在文件系統(tǒng)被安裝時,在內(nèi)存中組裝超級塊對象 */
          int (*get_sb) (struct file_system_type *, int,
                     const char *, void *, struct vfsmount *);
          /* 終止訪問超級塊 */
          void (*kill_sb) (struct super_block *);
          struct module *owner;           /* 文件系統(tǒng)模塊 */
          struct file_system_type * next; /* 鏈表中下一個文件系統(tǒng)類型 */
          struct list_head fs_supers;     /* 超級塊對象鏈表 */
      
          /* 下面都是運行時的鎖 */
          struct lock_class_key s_lock_key;
          struct lock_class_key s_umount_key;
      
          struct lock_class_key i_lock_key;
          struct lock_class_key i_mutex_key;
          struct lock_class_key i_mutex_dir_key;
          struct lock_class_key i_alloc_sem_key;
      };

      每種文件系統(tǒng),不管由多少個實例安裝到系統(tǒng)中,還是根本沒有安裝到系統(tǒng)中,都只有一個 file_system_type 結構。

       

      當文件系統(tǒng)被實際安裝時,會在安裝點創(chuàng)建一個 vfsmount 結構體。

      結構體代表文件系統(tǒng)的實例,也就是文件系統(tǒng)被安裝幾次,就會創(chuàng)建幾個 vfsmount

      vfsmount 的定義參見:<linux/mount.h>

      struct vfsmount {
          struct list_head mnt_hash;      /* 散列表 */
          struct vfsmount *mnt_parent;    /* 父文件系統(tǒng),也就是要掛載到哪個文件系統(tǒng) */
          struct dentry *mnt_mountpoint;    /* 安裝點的目錄項 */
          struct dentry *mnt_root;        /* 該文件系統(tǒng)的根目錄項 */
          struct super_block *mnt_sb;        /* 該文件系統(tǒng)的超級塊 */
          struct list_head mnt_mounts;    /* 子文件系統(tǒng)鏈表 */
          struct list_head mnt_child;        /* 子文件系統(tǒng)鏈表 */
          int mnt_flags;                  /* 安裝標志 */
          /* 4 bytes hole on 64bits arches */
          const char *mnt_devname;        /* 設備文件名 e.g. /dev/dsk/hda1 */
          struct list_head mnt_list;      /* 描述符鏈表 */
          struct list_head mnt_expire;    /* 到期鏈表的入口 */
          struct list_head mnt_share;        /* 共享安裝鏈表的入口 */
          struct list_head mnt_slave_list;/* 從安裝鏈表 */
          struct list_head mnt_slave;        /* 從安裝鏈表的入口 */
          struct vfsmount *mnt_master;    /* 從安裝鏈表的主人 */
          struct mnt_namespace *mnt_ns;    /* 相關的命名空間 */
          int mnt_id;            /* 安裝標識符 */
          int mnt_group_id;        /* 組標識符 */
          /*
           * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
           * to let these frequently modified fields in a separate cache line
           * (so that reads of mnt_flags wont ping-pong on SMP machines)
           */
          atomic_t mnt_count;         /* 使用計數(shù) */
          int mnt_expiry_mark;        /* 如果標記為到期,則為 True */
          int mnt_pinned;             /* "釘住"進程計數(shù) */
          int mnt_ghosts;             /* "鏡像"引用計數(shù) */
      #ifdef CONFIG_SMP
          int *mnt_writers;           /* 寫者引用計數(shù) */
      #else
          int mnt_writers;            /* 寫者引用計數(shù) */
      #endif
      };

       

      4. 進程相關的數(shù)據(jù)結構

      以上介紹的都是在內(nèi)核角度看到的 VFS 各個結構,所以結構體中包含的屬性非常多。

      而從進程的角度來看的話,大多數(shù)時候并不需要那么多的屬性,所有VFS通過以下3個結構體和進程緊密聯(lián)系在一起。

      - struct files_struct  :由進程描述符中的 files 目錄項指向,所有與單個進程相關的信息(比如打開的文件和文件描述符)都包含在其中。

      - struct fs_struct     :由進程描述符中的 fs 域指向,包含文件系統(tǒng)和進程相關的信息。

      - struct mmt_namespace :由進程描述符中的 mmt_namespace 域指向。

       

      struct files_struct 位于:<linux/fdtable.h>

      struct files_struct {
          atomic_t count;      /* 使用計數(shù) */
          struct fdtable *fdt; /* 指向其他fd表的指針 */
          struct fdtable fdtab;/* 基 fd 表 */
          spinlock_t file_lock ____cacheline_aligned_in_smp; /* 單個文件的鎖 */
          int next_fd;                                       /* 緩存下一個可用的fd */
          struct embedded_fd_set close_on_exec_init;         /* exec()時關閉的文件描述符鏈表 */
          struct embedded_fd_set open_fds_init;              /* 打開的文件描述符鏈表 */
          struct file * fd_array[NR_OPEN_DEFAULT];           /* 缺省的文件對象數(shù)組 */
      };

       

      struct fs_struct 位于:<linux/fs_struct.h>

      struct fs_struct {
          int users;               /* 用戶數(shù)目 */
          rwlock_t lock;           /* 保護結構體的讀寫鎖 */
          int umask;               /* 掩碼 */
          int in_exec;             /* 當前正在執(zhí)行的文件 */
          struct path root, pwd;   /* 根目錄路徑和當前工作目錄路徑 */
      };

       

      struct mmt_namespace 位于:<linux/mmt_namespace.h>

      但是在2.6內(nèi)核之后似乎沒有這個結構體了,而是用 struct nsproxy 來代替。

      以下是 struct task_struct 結構體中關于文件系統(tǒng)的3個屬性。

      struct task_struct 的定義位于:<linux/sched.h>

      /* filesystem information */
          struct fs_struct *fs;
      /* open file information */
          struct files_struct *files;
      /* namespaces */
          struct nsproxy *nsproxy;

       

      5. 小結

      VFS 統(tǒng)一了文件系統(tǒng)的實現(xiàn)框架,使得在linux上實現(xiàn)新文件系統(tǒng)的工作變得簡單。

      目前l(fā)inux內(nèi)核中已經(jīng)支持60多種文件系統(tǒng),具體支持的文件系統(tǒng)可以查看 內(nèi)核源碼 fs 文件夾下的內(nèi)容。

      posted @ 2013-06-19 15:43  wang_yb  閱讀(15078)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 精品国产91久久粉嫩懂色| 一区二区三区鲁丝不卡| 永久免费av无码网站直播| 韩国无码AV片午夜福利| 野花韩国高清电影| 国产成人精品久久性色av| 亚洲精品国模一区二区| 玛曲县| 实拍女处破www免费看| 成人精品天堂一区二区三区| 国产AV福利第一精品| 成人av天堂网在线观看| 国产一区二区日韩经典| 337p西西人体大胆瓣开下部| 精品少妇av蜜臀av| 徐汇区| 人成午夜免费视频无码| 亚洲第一香蕉视频啪啪爽| 国产乱人伦真实精品视频| 国产成人亚洲欧美二区综合| 国产在线观看免费观看| 绝顶丰满少妇av无码| 日本高清中文字幕免费一区二区| 亚洲女初尝黑人巨| 国产伦精区二区三区视频| 永清县| 国产欧美综合在线观看第十页 | 亚洲国产成熟视频在线多多 | 99久久激情国产精品| 亚洲无码a∨在线视频| 亚洲成人av高清在线| 国产男女猛烈无遮挡免费视频网站| 国产精品免费重口又黄又粗| 高潮潮喷奶水飞溅视频无码| 国产中文三级全黄| 曰韩精品无码一区二区三区视频| 欧美成人看片黄A免费看| 久久精品无码免费不卡| 亚洲天堂一区二区三区四区| 国产精品久久无码不卡黑寡妇| 老司机亚洲精品一区二区|