多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > Linux虛擬文件系統(VFS)學習

Linux虛擬文件系統(VFS)學習

來源:程序員人生   發布時間:2014-11-04 08:35:16 閱讀次數:3700次

  虛擬文件系統(Virtual Filesystem)也可稱之為虛擬文件系統轉換(Virtual Filesystem Switch),是1個內核軟件層,用來處理與Unix標準文件系統相干的所有系統調用。其硬朗性表現在能為各種文件系統提供1個通用的接口。

通用文件系統模型

  VFS所隱含的主要思想在于引入1個通用的文件系統模型(common file model),這個模型能夠表示所有支持的文件系統。在通用文件模型中,每一個目錄被看作1個文件,可以包括若干文件和其他的子目錄。

通用文件模型由以下對象類型組成:

超級塊對象(superblock object)

寄存已安裝文件系統的有關信息(A superblock object represents a mounted filesystem)。對基于磁盤的文件系統,這類對象通常對應于寄存在磁盤上的文件系統控制塊

索引節點對象(inode object)

寄存關于具體文件的1般信息(An inode object represents an object within the filesystem)。對基于磁盤的文件系統,這類對象通常對應于寄存在磁盤上的文件控制塊。每一個索引節點對象都有1個索引節點號,這個節點號唯1地標識文件系統中的文件。

文件對象(file object)

寄存打開文件與進程之間進行交互的有關信息(A file object represents a file opened by a process)。這類信息僅當進程訪問文件期間存在于內核內存中。

目錄項對象(dentry object)

寄存目錄項(也就是文件的特定名稱)與對應文件進行鏈接的有關信息。

VFS的數據結構

這里只羅列和進程相干的結構

索引節點對象

文件系統處理文件所需要的所有信息都放在1個名為索引節點的數據結構中。文件名可以隨時更改,但是索引節點對文件是唯1的,并且隨著文件的存在而存在。內存中索引節點對象由1個struct inode數據結構構成。

struct inode { struct hlist_node i_hash; //用于散列鏈表 struct list_head i_list; /* backing dev IO list */ struct list_head i_sb_list; struct list_head i_dentry; //援用索引節點的目錄項對象鏈表頭 unsigned long i_ino; //索引節點號 atomic_t i_count; //援用計數器 unsigned int i_nlink; //硬鏈接數目 uid_t i_uid; //所有者標識符 gid_t i_gid; //組標識符 dev_t i_rdev; //實裝備標識符 u64 i_version; //版本號(每次使用后遞增) loff_t i_size; //文件的字節數 #ifdef __NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount; #endif struct timespec i_atime; //上次訪問文件的時間 struct timespec i_mtime; //上次寫文件的時間 struct timespec i_ctime; //上次修改索引節點的時間 blkcnt_t i_blocks; //文件的塊數 unsigned int i_blkbits; //塊的位數 unsigned short i_bytes;//塊的字節數 umode_t i_mode; //文件的類型和訪問權限 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ struct mutex i_mutex; struct rw_semaphore i_alloc_sem; //在直接I/O文件操作中避免出現競爭條件的讀寫信號量 const struct inode_operations *i_op; //索引節點的操作 const struct file_operations *i_fop; /*缺省文件操作former ->i_op->default_file_ops */ struct super_block *i_sb; //指向超級塊的指針 struct file_lock *i_flock; struct address_space *i_mapping; //指向address_space對象的指針 struct address_space i_data; //文件的address_space對象 #ifdef CONFIG_QUOTA struct dquot *i_dquot[MAXQUOTAS]; //索引節點磁盤限額 #endif struct list_head i_devices; //用于具體的字符或塊裝備索引節點鏈表 union { struct pipe_inode_info *i_pipe; //如果文件是個管道則使用它 struct block_device *i_bdev; //指向塊裝備驅程序的指針 struct cdev *i_cdev; //指向字符裝備驅動程序的指針 }; __u32 i_generation; //索引節點的版本號 #ifdef CONFIG_FSNOTIFY __u32 i_fsnotify_mask; /* all events this inode cares about */ struct hlist_head i_fsnotify_mark_entries; /* fsnotify mark entries */ #endif #ifdef CONFIG_INOTIFY struct list_head inotify_watches; /* watches on this inode */ struct mutex inotify_mutex; /* protects the watches list */ #endif unsigned long i_state; //索引節點狀態標志 unsigned long dirtied_when; /* jiffies of first dirtying */ unsigned int i_flags; //文件系統安裝標志 atomic_t i_writecount; #ifdef CONFIG_SECURITY void *i_security; #endif #ifdef CONFIG_FS_POSIX_ACL struct posix_acl *i_acl; struct posix_acl *i_default_acl; #endif void *i_private; /* fs or device private pointer */ };
文件對象

文件對象描寫進程怎樣與1個打開的文件進行交互。文件對象是在文件被打開時創建的,由1個file結構組成。文件對象在磁盤上是沒有對應的映像,因此file結構中沒有設置“臟”字段來表示文件對象是不是已被修改。

struct file { /* * fu_list becomes invalid after file_free is called and queued via * fu_rcuhead for RCU freeing */ union { struct list_head fu_list; struct rcu_head fu_rcuhead; } f_u; struct path f_path; #define f_dentry f_path.dentry //與文件相干的目錄項對象 #define f_vfsmnt f_path.mnt //含有該文件的已安裝文件系統 const struct file_operations *f_op; //文件操作表指針 spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */ atomic_long_t f_count; //文件對象的援用計數器 unsigned int f_flags; //當打開文件時所指定的標志 fmode_t f_mode; //進程訪問模式 loff_t f_pos; //當前的文件偏移量 struct fown_struct f_owner; //通過信號進行I/O事件通知的數據 const struct cred *f_cred; struct file_ra_state f_ra; //文件預讀狀態 u64 f_version; //版本號,每次使用后自動遞增 #ifdef CONFIG_SECURITY void *f_security; #endif /* needed for tty driver, and maybe others */ void *private_data;//指向特定文件系統或裝備驅動程序所需要數據的指針 #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_head f_ep_links;//文件的事件輪詢等待著鏈表頭 #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping;//指向文件地址空間對象的指針 #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif };
文件對象通過1個名為filp的slab高速緩存分配,filp描寫符地址寄存在filp_cachep變量中。由于分配的文件對象數目是有限的,因此files_stat變量在其max_files字段中指定了可分配的文件對象的最大數目,也就是系統可同時訪問的最大文件數。

內核初始化期間,files_init()函數把max_files字段設置為可用RAM大小的1/10。不過,系統管理員可以通過寫/proc/sys/fs/file-max文件來修改這個值。而且即便max_files個文件對象已被分配,超級用戶也總是可以取得1個文件對象

void __init files_init(unsigned long mempages) { int n; filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); /* * One file with associated inode and dcache is very roughly 1K. * Per default don't use more than 10% of our memory for files. */ n = (mempages * (PAGE_SIZE / 1024)) / 10; files_stat.max_files = n; if (files_stat.max_files < NR_FILE) files_stat.max_files = NR_FILE; files_defer_init(); percpu_counter_init(&nr_files, 0); }
目錄項對象

VFS把每一個目錄看作若干子目錄和文件組成的1個普通文件。1旦目錄項被讀入內存,VFS就把它轉換成基于dentry結構的1個目錄項對象。對進程查找的路徑名中的每一個份量,內核都為其創建1個目錄項對象;目錄項對象將每一個份量與其對應的索引節點相聯系。例如在查找路徑名/tmp/test時,內核為根目錄“/”創建1個目錄項對象,為根目錄下的tmp項創建第2級目錄項對象,為/tmp目錄下的test創建1個第3級目錄項對象。

目錄項對象在磁盤上并沒有對應的映像,因此在dentry結構中不包括指出該對象已被修改的字段。目錄項對象寄存在名為dentry_cache的高速緩存中。

struct dentry { atomic_t d_count; //目錄項對象援用計數 unsigned int d_flags; /* 目錄項高速緩存標志protected by d_lock */ spinlock_t d_lock; /* per dentry lock */ int d_mounted; //對目錄而言,用于記錄安裝該目錄項的文件系統計數器 struct inode *d_inode; /* 與文件名關聯的索引節點Where the name belongs to - NULL is * negative */ /* * The next three fields are touched by __d_lookup. Place them here * so they all fit in a cache line. */ struct hlist_node d_hash; /* lookup hash list */ struct dentry *d_parent; /* 父目錄的目錄項對象parent directory */ struct qstr d_name; //文件名 struct list_head d_lru; /* LRU list */ /* * 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; /* our children */ struct list_head d_alias; /* inode alias list */ unsigned long d_time; /* used by d_revalidate */ const struct dentry_operations *d_op;//目錄項方法 struct super_block *d_sb; /* 文件的超級塊對象The root of the dentry tree */ void *d_fsdata; /* 依賴于文件系統的數據fs-specific data */ unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ };
與進程相干的文件

每一個進程都有它自己當前的工作目錄和他自己的根目錄。這僅僅是內核用來表示進程與文件系統相互作用所必須保護的數據的兩個例子。類型為fs_struct的全部數據結構就用于此目的

struct fs_struct { int users; rwlock_t lock; int umask; //當打開文件設置文件權限是所用的位掩碼 int in_exec; struct path root, pwd; /* 根目錄的目錄項,根目錄所安裝的文件系統對象 當前工作的目錄項,當前工作目錄所安裝的文件系統對象*/ };
進程當前打開的文件與files_struct結構有關

struct fdtable { unsigned int max_fds; //文件對象確當前最大數目 struct file ** fd; /* current fd array */ fd_set *close_on_exec; fd_set *open_fds; struct rcu_head rcu; struct fdtable *next; }; /* * Open file table structure */ struct files_struct { /* * read mostly part */ atomic_t count; //同享進程的數目 struct fdtable *fdt; // struct fdtable fdtab; /* * written part on a separate cache line in SMP */ spinlock_t file_lock ____cacheline_aligned_in_smp; int next_fd; struct embedded_fd_set close_on_exec_init; struct embedded_fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT];//文件對象指針的初始化數組 };

fd字段指向文件對象的指針數組。該數組的長度寄存在max_fds字段中。通常,fd字段指向files_struct結構中的fd_array字段,該字段包括32個文件對象指針。如果進程打開的文件數據多于32,內核就分配1個新的、更大的文件指針數組,并將其地址寄存在fd字段中,內核同時更新max_fds字段的值。

對應fd數組中有元素的每一個文件來講,數組的索引就是文件描寫符。通常,數組的第1個元素(索引0)是進程的標準輸入文件,數組的第2個元素(索引1)是進程的標準輸出文件,數組的第3個元素(索引2)是進程的標準毛病輸出文件。
內核在進程描寫符的signal->rlim[RLIM_NLIMITS]結構上強迫動態限制文件描寫符的最大數;這個值通常為1024,但如果進程具有超級權限,就能夠增大這個值。

最經常使用的特殊文件系統類型

名字           安點綴     說明

bdev           無        塊裝備

binfmt_misc    任意      其他可履行格式

devpts         /dev/pts  偽終端支持

eventpollfs    無        由有效事件輪詢機制使用

futexfs        無        由futex(快速用戶態加鎖)機制使用

pipefs         無        管道

proc           /proc     對內核數據結構的常規訪問點

rootfs         無        為啟動階段提供1個空的根目錄

shm            無        IPC同享線性區

mqueue         任意       實現POSIX消息隊列時使用

sockfs         無         套接字

sysfs          /sys       對系統參數的常規訪問

tmpfs          任意        臨時文件(如果不被交換出去就保持在RAM中)

usbfs          /proc/bus/usb USB裝備

文件系統注冊

每一個注冊的文件系統都用1個類型為file_system_type的對象來表示

struct file_system_type { const char *name; //文件系統名 int fs_flags; //文件系統標志 int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); //讀取超級塊的方法 void (*kill_sb) (struct super_block *); //刪除超級塊的方法 struct module *owner; //指向實現文件系統的模塊的指針 struct file_system_type * next;//指向文件系統鏈表中下1個元素的指針 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; };
以sockfs文件系統注冊為例

static struct file_system_type sock_fs_type = { .name = "sockfs", .get_sb = sockfs_get_sb, .kill_sb = kill_anon_super, }; static int __init sock_init(void) { /* * Initialize sock SLAB cache. */ sk_init(); /* * Initialize skbuff SLAB cache */ skb_init(); /* * Initialize the protocols module. */ init_inodecache(); /* 注冊sockfs文件系統 */ register_filesystem(&sock_fs_type); sock_mnt = kern_mount(&sock_fs_type); /* The real protocol initialization is performed in later initcalls. */ #ifdef CONFIG_NETFILTER netfilter_init(); #endif return 0; }

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产成人小视频在线观看 | 成人自拍在线 | 日本xxxwww免费视频 | 欧美日韩第三页 | 午夜美女写真福利写视频 | 一级做a爱 | 久久久欧美综合久久久久 | 亚洲人成综合在线播放 | 欧美国产日韩一区 | 操人网| 亚洲淫片| 性freexxxxhd欧美在线 | 98精品全国免费观看视频 | 欧美在线免费 | 欧美freesex交| 久久久久亚洲国产 | 韩国在线观看免费观看影院 | 国产女人18毛片水真多18精品 | 日韩欧美一区二区三区四区 | 免费尤物视频 | 欧美ucjizz免费播放器 | 国产大片www| 久久综合欧美 | 最新欧美精品一区二区三区不卡 | 久久久久欧美精品网站 | 亚洲精品免费在线视频 | 久久精品国产亚洲精品 | 亚洲 校园 欧美 动漫 制服 | 久久久精品久久久久久 | 亚洲图片在线 | 亚洲一一在线 | 日本亚洲乱码中文字幕影院 | 亚洲第一视频网站 | 亚洲一区二区三区不卡视频 | 国产精品久久久久久免费 | 精品久久久久不卡无毒 | 日韩欧美亚洲一区精选 | 永久免费毛片在线播放 | 日本一级高清不卡视频在线 | 中文字幕在线观看一区二区三区 | 天天成人综合网 |