一、 概述
二、 VFS相关的数据结构以及其分析
struct super_block {
struct list_head s_list;
/*
指向超级块链表的指针
*/
/*
*
包含该具体文件系统的块设备标识符。
*例如,对于 /dev/hda1,其设备标识符为 0x301
*/
kdev_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;
/*
指向某个特定的具体文件系统的用于超级块操作的函数集合的指针
*/
struct super_operations *s_op;
struct dquot_operations *dq_op;
/*
指向磁盘限额方法的指针
*/
unsigned long s_flags;
/*
魔数,即该具体文件系统区别于其它文系统的一个标志
*/
unsigned long s_magic;
struct dentry *s_root;
struct rw_semaphore s_umount;
struct semaphore s_lock;
int s_count;
atomic_t s_active;
struct list_head s_dirty;
/*
已修改索引节点的链表
*/
struct list_head s_locked_inodes;
/*
涉及
I/O
的索引节点的链表
*/
struct list_head s_files;
/*
分配给超级的文件对象的链表
*/
struct block_device *s_bdev;
struct list_head s_instances;
struct quota_mount_options s_dquot;
/*
磁盘限额的选项
*/
/*
一个共用体,其成员是各种文件系统的
fsname_sb_info
数据结构
*/
union {
struct minix_sb_info minix_sb;
struct ext2_sb_info ext2_sb;
struct ext3_sb_info ext3_sb;
struct hpfs_sb_info hpfs_sb;
struct ntfs_sb_info ntfs_sb;
struct msdos_sb_info msdos_sb;
struct isofs_sb_info isofs_sb;
struct nfs_sb_info nfs_sb;
struct sysv_sb_info sysv_sb;
struct affs_sb_info affs_sb;
struct ufs_sb_info ufs_sb;
struct efs_sb_info efs_sb;
struct shmem_sb_info shmem_sb;
struct romfs_sb_info romfs_sb;
struct smb_sb_info smbfs_sb;
struct hfs_sb_info hfs_sb;
struct adfs_sb_info adfs_sb;
struct qnx4_sb_info qnx4_sb;
struct reiserfs_sb_info reiserfs_sb;
struct bfs_sb_info bfs_sb;
struct udf_sb_info udf_sb;
struct ncp_sb_info ncpfs_sb;
struct usbdev_sb_info usbdevfs_sb;
struct jffs2_sb_info jffs2_sb;
struct cramfs_sb_info cramfs_sb;
void *generic_sbp;
} u;
struct semaphore s_vfs_rename_sem;
struct semaphore s_nfsd_free_path_sem;
};
|
struct inode {
/**********
描述索引节点高速缓存管理的域
***********/
struct list_head i_hash; /*
指向哈希链表的指针
*/
struct list_head i_list; /*
指向索引节点链表的指针
*/
struct list_head i_dentry; /*
指向目录项链表的指针
*/
struct list_head i_dirty_buffers;
struct list_head i_dirty_data_buffers;
/**********
描述文件信息的域
****************/
unsigned long i_ino; /*
索引节点号
*/
atomic_t i_count; /*引用计数器*/ kdev_t i_dev; /*设备标识号 */
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid; /*
文件拥有者标识号
*/
gid_t i_gid; /*
文件拥有者所在组的标识号
*/
kdev_t i_rdev; /*
实际设备标识号
*/
loff_t i_size;
time_t i_atime; /*
文件的最后访问时间
*/
time_t i_mtime; /*
文件的最后修改时间
*/
time_t i_ctime; /*
节点的修改时间
*/
unsigned int i_blkbits; /*
块的位数
*/
unsigned long i_blksize; /*
块大小
*/
unsigned long i_blocks; /*
该文件所占块数
*/
unsigned long i_version; /*
版本号
*/
struct semaphore i_sem;
struct semaphore i_zombie; /*
僵死索引节点的信号量
*/
struct inode_operations *i_op; /*索引节点的操作*/
struct file_operations *i_fop; /*
指向缺省的文件操作
*/
struct super_block *i_sb; /*指向该文件系统超级块的指针 */
wait_queue_head_t i_wait; /*
指向索引节点等待队列的指针
*/
struct file_lock *i_flock; /*
指向文件加锁链表的指针
*/
/************
用于分页机制的域
***************/
struct address_space *i_mapping; /*
把所有可交换的页面管理起来
*/
struct address_space i_data;
struct dquot *i_dquot[MAXQUOTAS];
/*
以下几个域应当是联合体
*/
struct list_head i_devices; /*
设备文件形成的链表
*/
struct pipe_inode_info *i_pipe; /*指向管道文件*/ struct block_device *i_bdev; /*指向块设备文件的指针*/
struct char_device *i_cdev; /*
指向字符设备文件的指针
*/
unsigned long i_dnotify_mask; /*
目录通知事件标志
*/
struct dnotify_struct *i_dnotify;
unsigned long i_state; /*
索引节点的状态标志
*/
unsigned int i_flags; /*
文件系统的安装标志
*/
unsigned char i_sock; /*
如果是套接字文件则为真
*/
atomic_t i_writecount; /*
写进程的引用计数
*/
unsigned int i_attr_flags; /*
文件创建标志
*/
__u32 i_generation;
/*
*
类似于超级块的一个共用体,其成员是各种具体
*
文件系统的
fsname_inode_info
数据结构
*/
union {
struct minix_inode_info minix_i;
struct ext2_inode_info ext2_i;
struct ext3_inode_info ext3_i;
struct hpfs_inode_info hpfs_i;
struct ntfs_inode_info ntfs_i;
struct msdos_inode_info msdos_i;
struct umsdos_inode_info umsdos_i;
struct iso_inode_info isofs_i;
struct nfs_inode_info nfs_i;
struct sysv_inode_info sysv_i;
struct affs_inode_info affs_i;
struct ufs_inode_info ufs_i;
struct efs_inode_info efs_i;
struct romfs_inode_info romfs_i;
struct shmem_inode_info shmem_i;
struct coda_inode_info coda_i;
struct smb_inode_info smbfs_i;
struct hfs_inode_info hfs_i;
struct adfs_inode_info adfs_i;
struct qnx4_inode_info qnx4_i;
struct reiserfs_inode_info reiserfs_i;
struct bfs_inode_info bfs_i;
struct udf_inode_info udf_i;
struct ncp_inode_info ncpfs_i;
struct proc_inode_info proc_i;
struct socket socket_i;
struct usbdev_inode_info usbdev_i;
struct jffs2_inode_info jffs2_i;
void *generic_ip;
} u;
};
|
dentry 的定义在include/linux/dcache.h中:
struct dentry {
atomic_t d_count;
/*
目录项引用计数器
*/
unsigned int d_flags; /*目录项标志*/ struct inode * d_inode; /*与文件名关联的索引节点*/ struct dentry * d_parent; /*父目录的目录项*/ struct list_head d_hash; /*目录项形成的哈希表*/ struct list_head d_lru; /*未使用的 LRU 链表*/ struct list_head d_child; /*父目录的子目录项所形成的链表*/
struct list_head d_subdirs;
/*
该目录项的子目录所形成的链表
*/
struct list_head d_alias;
/*
索引节点别名的链表
*/
int d_mounted;
/*
目录项的安装点
*/
struct qstr d_name; /*目录项名(可快速查找) */ unsigned long d_time; /*由 d_revalidate函数使用*/
struct dentry_operations *d_op;
/*
目录项的函数集
*/
struct super_block * d_sb;
/*
目录项树的根(即文件的超级块)
*/
unsigned long d_vfs_flags;
void * d_fsdata;
/*
具体文件系统的数据
*/
unsigned char d_iname[DNAME_INLINE_LEN]; /*短文件名*/
};
|
struct file {
struct list_head
f_list;
/*
所有打开的文件形成一个链表
*/
struct dentry *f_dentry; /*指向相关目录项的指针*/ struct vfsmount *f_vfsmnt;/*指向VFS安装点的指针*/ struct file_operations *f_op; /*指向文件操作表的指针*/
atomic_t f_count;
/*
文件对象的引用计数器
*/
unsigned int f_flags; /*打开文件时所指定的标志*/
mode_t f_mode;
/*
文件的打开模式
*/
loff_t f_pos;
/*
文件的当前位置
*/
/*
预读标志、要预读的最多页面数、上次预读后的文
件指针、预读的字节数以及预读的页面数
*/
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; struct fown_struct f_owner; unsigned int f_uid, f_gid;
int f_error;
unsigned long f_version;
void *private_data;
/* tty
驱动程序所需
*/
/*
用于直接访问缓冲区的描述符
*/
struct kiobuf *f_iobuf;
long f_iobuf_lock;
};
|
三、 文件系统的mount操作
struct vfsmount
{
struct list_head mnt_hash; struct vfsmount *mnt_parent; /*所挂载的文件系统*/ struct dentry *mnt_mountpoint; /*挂载点目录*/ struct dentry *mnt_root; /*挂载文件树的根目录*/ struct super_block *mnt_sb; /*指向超级块的指针*/ struct list_head mnt_mounts; /*描述符父链表的头*/ struct list_head mnt_child; /*用于描述父链表的指针*/ atomic_t mnt_count; int mnt_flags; char *mnt_devname; /*设备名称*/ struct list_head mnt_list;
};
|
例如: # mount 2t msdos/dev/hdc/mnt/usr其中msdos 是要安装的文件系统类型, /dev/hdc 是文件系统所在的设备,/mnt/usr是安装点。
(1) 寻找对应的文件系统信息,VFS 通过filesystems在file- system- type 组成的链表中根据指定的文件系统名称搜索文件系统类型信息。
(2) 如果在上述链表中找到匹配的文件系统,则说明内核具有对该文件系统的内建支持。 否则,说明该文件系统可能由可装载模块支持,VFS 会请求内核装入相应原文件系统模块,此时,该文件系统在VFS 中注册并初始化。
(4) VFS 检验指定的物理块设备是否已经安装。 如果指定的块设备已被安装,则返回错误。
四、 VFS的read操作
asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count)
{
ssize_t ret;
struct file * file;
ret = -EBADF; file = fget(fd); if (file) { if (file->f_mode & FMODE_READ) { ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, file, file->f_pos, count); if (!ret) { ssize_t (*read)(struct file *, char *, size_t, loff_t *); ret = -EINVAL; if (file->f_op && (read = file->f_op->read) != NULL)
ret = read(file, buf, count, &file->f_pos);
}
}
if (ret > 0) dnotify_parent(file->f_dentry, DN_ACCESS);
fput(file);
}
return ret;
}
|
struct file_operations {
struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *);
……
};
|