2011-7-10 15:27:45
来源:互联网 发布:滑板价格淘宝网 编辑:程序博客网 时间:2024/06/12 03:44
2011-7-10 15:27:45
虚拟文件系统介绍
Linux支持各种文件系统,Linux内核通过虚拟文件系统了对各种文件系统共性的进行抽象,并对外提供统一接口,从面向对象编程的角度来看,
称为抽象文件系统更为合适。虚拟文件系统(VFS virtual file system)用来管理挂接(mount)各种具体文件系统(如:ext4文件系统)。
具体的文件系统可设计成可加载模块,在系统需要时进行加载,例如VFAT就被实现成一个模块,当挂接VFAT文件系统时VFAT文件系统模块将被加载。
挂接具体文件系统时,VFS读取它的超级块,得到具体文件系统的拓扑结构并将这些信息映射到VFS超级块结构中。
当进程或shell命令(如:ls)访问目录和文件时,shell命令及应用程序分解成系统调用,系统调用进入内核空间,遍历虚拟文件系统的VFS节点(inode),
而VFS节点指向了具体文件系统的节点,通过底层块I/O函数调用IDE接口,然后再通过块驱动程序访问块设备(如:硬盘),得到了文件数据。
文件系统的运行流程示意图如图7-1。
虚拟文件系统对文件系统共有的内核上层及底层部分进行了处理,上层处理如:文件路径的查找、文件的读写操作从用户空间向下传递到具体文件系统的部分;
底层进行各种缓存的处理,如:块缓存(buffer)。
虚拟文件系统机制
虚拟文件系统是文件系统共性的抽象,由超级块(superblock)、索引节点(inode)、文件(file)、目录 (dentry)对象组成,每个对象用数据结构进行描述。
它通过系统调用向用户空间提供了API操作文件系统,通过对象操作函数API调用具体文件系统的函数进行读写文件操作。 虚拟文件系统的对象说明如下:
超级块
超级块存放已安装文件系统的信息,与具体文件系统的超级块相对应。超级块由超级块对象结构super_block和超级块操作函数集结构super_operation组成。
索引节点
索引节点存放文件的通用信息,索引节点由索引节点对象结构inode和每个索引节点对象和索引节点操作函数集结构inode_operation组成。每个节点有一个节点号,
用于惟一地标识文件系统中的文件。
文件
文件对象描述了进程与打开文件之间交互过程的信息,目录文件存放目录中的文件列表信息。文件由文件对象结构file和文件操作函数集结构file operation组成。
文件对象的文件指针描述了文件中当前操作的位置,几个进程可以并发访问同一个文件。
目录条目(dentry)
文件系统的每个目录用目录条目对象结构dentry描述。例如,在查找/tmp/test/目录时,VFS为根目录"/"创建一个目录条目对象,
为tmp目录创建一个第二级目录条目对象,为test目录创建一个第三级目录条目对象。 目录条目对象在磁盘上并没有对应的映像,每个具体文件系统都有独特的
方式将目录条目信存放在磁盘上。
VFS数据结构
VFS的数据结构定义了VFS对象和对象的操作函数集,它们是一个接口标准,具体文件系统必须提供VFS接口标准对应的数据结构和操作函数。体文件系统在使用前,必须将自己的结构及操作函数映射到VFS中,这样被访问到。
超级块
超级块对象
VFS用超级块结构super_block描述整个文件系统信息,包括具体文件系统类型、起始级块操作函数、根目录、设备序号、等待队列、具体文件系统信息等数据。超级块是各种具体逻辑文件系统(如:ext4)在挂接时建立的,并在这些文件系统卸载时自动删除, 超级块确实只存在内存中,超级块是针对具体逻辑文件系统的。
每个具体文件系统挂接时,用具体文件系统的信息填充一个超级块结构实例,每个已挂接的文件系统有一个超级块对象,所有挂接文件系统的超级块对象链接成链表。
通常每个具体的文件系统有一个超级块信息结构,如:ext4_sb_info,超级块通过指针s_fs_info指向它。
超级块结构super_block列出如下(在include/linux/fs.h中):
struct super_block {
struct list_head s_list; /*超级块链表,必须在结构的最前面 */
/*包含该逻辑文件系统的块设备标识号。如:/dev/hda1设备标识符为0x301*/
dev_t s_dev;
/*该逻辑文件系统中数据块的大小,以字节为单位*/
unsigned long s_blocksize;
/*块大小的值占用的位数,如:1024字节时为10位*/
unsigned char s_blocksize_bits;
/*脏位,若置该位,表明该超级块已被修改*/
unsigned char s_dirt;
unsigned long long s_maxbytes; /*最大文件长度*/
struct file_system_type *s_type; /*文件系统类型*/
const struct super_operations *s_op; /*特定逻辑文件系统的超级块操作函数集*/
struct dquot_operations *dq_op; /*特定逻辑文件系统的限额操作函数集*/
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; /*卸载用的读/写信号量*/
struct mutex s_lock; /*超级块互斥锁*/
int s_count; /*引用计数器*/
int s_syncing; /*对超级块的索引节点进行同步的标志*/
int s_need_sync_fs; /*已挂接文件系统需要同步的标识*/
atomic_t s_active; /*
#ifdef CONFIG_SECURITY
void *s_security; /*用于SELinux的安全数据结构指针*/
#endif
struct xattr_handler **s_xattr; /*超级块扩展属性处理例程结构指针*/
struct list_head s_inodes; /* 所有索引节点的链表 */
struct list_head s_dirty; /* 脏索引节点的链表 */
struct list_head s_io; /*等待写回到磁盘的索引节点的链表 */
struct list_head s_more_io; /* parked for more writeback */
struct hlist_head s_anon; /*用于NFS输出的匿名目录条目的链表*/
struct list_head s_files; /*文件对象的链表*/
struct block_device *s_bdev; /*指向块设备描述结构*/
struct mtd_info *s_mtd; /*指向MTD设备信息结构*/
struct list_head s_instances; /*文件系统的超级块实例的链表*/
struct quota_info s_dquot; /* 磁盘限额特定选项信息*/
int s_frozen; /*冻结文件系统的标识*/
wait_queue_head_t s_wait_unfrozen; /*等待解冻文件系统的进程队列*/
char s_id[32]; /* 超级块可提供信息的名字 */
void *s_fs_info; /* 特定具体文件系统的超级块信息结构*/
/*下面的域仅用于VFS */
struct mutex s_vfs_rename_mutex; /* 当VFS通过目录重命名文件时用的互斥锁 */
u32 s_time_gran; /* 时间戳粒度(纳秒)*/
/*如果在/proc/mounts下的文件类型域非空,则文件类型域格式为“type.subtype”*/
char *s_subtype;
/*为使用generic_show_options()的懒惰文件系统存放挂接选项 */
char *s_options;
};
超级块操作函数集
超级块对象的各种操作方法由超级块操作函数集结构super_operations定义,通过超级块对象的成员s_op可找到该操作函数集,如:sb->s_op->read_inode(inode)。
结构super_operations列出如下:
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *sb); /*分配节点对象空间*/
void (*destroy_inode)(struct inode *); /*销毁节点*/
void (*dirty_inode) (struct inode *); /*处理脏节点,ext4用它更新文件系统日志*/
int (*write_inode) (struct inode *, int); /*将节点的内容写回到磁盘节点*/
/*通常为函数generic_drop_inode,当引用计数和硬连接计数i_nlink为0时,调用delete_inode删除节点*/
void (*drop_inode) (struct inode *);
void (*delete_inode) (struct inode *); /*删除节点及对应磁盘上的数据*/
void (*put_super) (struct super_block *); /*释放超级块对象*/
void (*write_super) (struct super_block *); /*将超级块信息写回磁盘*/
/*日志系统用来同步更新文件系统数据结构在磁盘上的数据*/
int (*sync_fs)(struct super_block *sb, int wait);
void (*write_super_lockfs) (struct super_block *); /*锁住文件系统将超级块信息写回磁盘*/
void (*unlockfs) (struct super_block *); /*解锁文件系统*/
int (*statfs) (struct dentry *, struct kstatfs *); /*得到文件系统的一些统计信息*/
int (*remount_fs) (struct super_block *, int *, char *); /*重新挂接文件系统*/
void (*clear_inode) (struct inode *); /*清除节点*/
void (*umount_begin) (struct super_block *); /*开始卸载文件系统的操作*、
int (*show_options)(struct seq_file *, struct vfsmount *); /*显示文件系统特定的选项*/
int (*show_stats)(struct seq_file *, struct vfsmount *); /*显示状态信息*/
#ifdef CONFIG_QUOTA
/*读限额,限额系统调用用该方法读取数据*/
ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
/*写限额,限额系统调用用该方法将数据写入文件*/
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
#endif
};
节点
节点对象在磁盘上有对应的映像,Linux内核需要负责节点对象的数据与磁盘上映像数据的一致性,这通过节点的状态标识完成。
索引节点对象
文件(包括目录文件)是管理文件系统的最基本单位,每个文件都有一个索引节点结构inode,存放了文件系统处理文件所需要的各种信息。
节点或索引节点(inode)是文件系统连接任何子目录、任何文件的桥梁。每个子目录或文件只能由惟一的inode描述。它包括结构操作函数、文件操作函数、
等待队列、对应物理块的描述等。
结构inode包括描述文件信息域、索引节点操作域和其他域。文件信息域包括时间戳、块数、文件大小、操作权限、用户ID等文件的信息;索引节点操作域包括文件锁、
文件操作函数集、节点操作函数集、节点脏标识和节点磁盘限额等操作文件所需要的操作函数或信息。
结构inode列出如下(在include/linux/fs.h中):
struct inode {
/*用Hash表加快索引节点的搜索,前提是系统需要知道索引节点号及所在文件系统的超级块地址*/
struct hlist_node i_hash; /*用于指向散列到同一地址的前一个索引节点和后一个索引节点*/
struct list_head i_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; /*SMP系统为i_size字段获取一致值时使用的顺序计数器*/
#endif
struct timespec i_atime; /*文件的最后访问时间*/
struct timespec i_mtime; /*文件的最后修改时间*/
struct timespec i_ctime; /*节点的最后修改时间*/
unsigned int i_blkbits; /*块大小所占的位数*/
blkcnt_t i_blocks; /*该文件所占块数*/
unsigned short i_bytes; /*文件最后一块所占字节数*/
umode_t i_mode; /*文件的访问权限*/
spinlock_t i_lock; /*保护i_blocks, i_bytes和i_size的自旋锁*/
struct mutex i_mutex; /*索引节点对象的互斥锁*/
struct rw_semaphore i_alloc_sem; /*直接I/O文件操作中用的读/写信号量*/
const struct inode_operations *i_op; /*索引节点的操作函数集*/
/* 缺省的文件操作函数集:former ->i_op->default_file_ops */
const struct file_operations *i_fop;
struct super_block *i_sb; /*指向超级块对象*/
struct file_lock *i_flock; /*指向文件锁*/
struct address_space *i_mapping; /*指向地址映射空间的指针*/
struct address_space i_data; /*文件数据的地址映射空间*/
#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; /*指向字符设备描述结构*/
};
int i_cindex; /*有次设备号的设备文件的索引*/
__u32 i_generation; /*指节点的不同软件版本,有些文件系统使用它*/
#ifdef CONFIG_DNOTIFY /*用于目录通知机制,当目录发生变化时,发出通知*/
unsigned long i_dnotify_mask; /* 目录通知事件*/
struct dnotify_struct *i_dnotify; /* 用于目录通知的结构*/
#endif
#ifdef CONFIG_INOTIFY /*用于节点通知机制,当节点发生变化时,发出通知*/
struct list_head inotify_watches; /* 监视此节点 */
struct mutex inotify_mutex; /* 用于保护监视链表的互斥锁*/
#endif
unsigned long i_state; /*索引节点的状态标识*/
unsigned long dirtied_when; /* 第1次设置脏位的时间(jiffies)*/
unsigned int i_flags; /*文件系统的挂接标志*/
atomic_t i_writecount; /*写操作的引用计数*/
#ifdef CONFIG_SECURITY
void *i_security; /*用于SELinux的安全结构*/
#endif
void *i_private; /* 指向文件系统或设备的私有数据*/
};
VFS的索引节点结构存有文件或目录的信息,具体文件系统的索引节点是存储在磁盘上的,是一种静态结构,又称为磁盘索引节点。每个磁盘索引节点有个节点号,
节点号用于指向文件的索引节点所在磁盘地址。
Linux用磁盘索引节点的数据填写VFS的索引节点,也称VFS索引节点是动态节点,通常所说的索引节点指的是VFS索引节点,是结构inode的对象实例。
- 2011-7-10 15:27:45
- 2011-7-10 15:14:00
- 2011-7-10 15:32:09
- 2011-10-27 jsp
- 2011-10-27
- 2011-10-27
- NYOJ-844-A+B Problem(V)-2013年10月27日15:17:45
- 2011。7。15
- 2011/10/08~10/15
- 2011-10-10 0:27:53
- 2011-7-13 13:00:45
- 2011-9-27 21:15:52
- 2011-06-07 10:45:12
- 2011-8-10 21:44:45
- 8/31/2011 10:51:45 AM
- 2011/10/7
- 2011-7-15 讨论会笔记
- 6/26/2011 7:27:13 PM
- 简单虚拟块设备驱动流程
- 2011-7-10 15:14:00
- 抓虫记之五:Webservice总是调用不了
- windows程序设计之对话框简介1
- 字符串的相互转换
- 2011-7-10 15:27:45
- 线性表的顺序存储结构之顺序表类的实现_Java
- Chat聊天系统雏形
- What comes after genome sequencing?
- 驱动实现异步通知
- Linux 启动级别详解
- 兆鹏带你读watir——浅谈基于watir的前端敏捷测试
- select、poll和epoll
- 用POI把数据导出为Excel