- 论坛徽章:
- 0
|
使用户可以直接使用系统调用而无需考虑具体文件系统或实际物理介质。
12.2 文件系统抽象层
之所以可以用这种通用接口对所有类型的文件系统进行操作,是因为内核在底层文件系统接口上建立了一个抽象层,定义了所有文件系统都支持的基本接口和数据结构。
例如:
write()调用将来自用户空间的数据流,首先通过VFS通用系统调用,其次通过文件系统的特殊写方法,写入物理介质。
12.3 Unix文件系统
(1) 文件——有序字节串
(2) 目录项
(3) 索引节点——文件的相关信息,包括访问控制权限、大小、拥有者、创建时间等
(4) 安装点
12.4 VFS对象及数据结构
四个主要的对象类型:
(1) 超级块对象,代表一个已安装的文件系统
(2) 索引节点对象,代表一个文件
(3) 目录项对象,代表一个目录项,是路径的一个组成部分
(4) 文件对象,代表由进程打开的文件
主要的操作对象:
(1) super_operations对象——内核针对特定文件系统所能调用的方法,read_inode()、sync_fs()等;
(2) inode_operations对象——内核对特定文件所能调用的方法,create()、link()等;
(3) dentry_operations对象——内核对特定目录所能调用的方法,d_compare()、d_delete()等;
(4) file对象——进程对已代开文件所能调用的方法,read()、write()等。
12.5 超级块对象
存储特定文件系统信息,存放于磁盘特定扇区中。
struct super_block {
struct list_head s_list; /* list of all superblocks */
dev_t s_dev; /* identifier */
unsigned long s_blocksize; /* block size in bytes */
unsigned long s_old_blocksize; /* old block size in bytes */
unsigned char s_blocksize_bits; /* block size in bits */
unsigned char s_dirt; /* dirty flag */
unsigned long long s_maxbytes; /* max file size */
struct file_system_type s_type; /* filesystem type */
struct super_operations s_op; /* superblock methods */
struct dquot_operations *dq_op; /* quota methods */
struct quotactl_ops *s_qcop; /* quota control methods */
struct export_operations *s_export_op; /* export methods */
unsigned long s_flags; /* mount flags */
unsigned long s_magic; /* filesystem's magic number */
struct dentry *s_root; /* directory mount point */
struct rw_semaphore s_umount; /* unmount semaphore */
struct semaphore s_lock; /* superblock semaphore */
int s_count; /* superblock ref count */
int s_syncing; /* filesystem syncing flag */
int s_need_sync_fs; /* not-yet-synced flag */
atomic_t s_active; /* active reference count */
void *s_security; /* security module */
struct list_head s_dirty; /* list of dirty inodes */
struct list_head s_io; /* list of writebacks */
struct hlist_head s_anon; /* anonymous dentries */
struct list_head s_files; /* list of assigned files */
struct block_device *s_bdev; /* associated block device */
struct list_head s_instances; /* instances of this fs */
struct quota_info s_dquot; /* quota-specific options */
char s_id[32]; /* text name */
void *s_fs_info; /* filesystem-specific info */
struct semaphore s_vfs_rename_sem; /* rename semaphore */
};
struct super_operations {
struct inode *(*alloc_inode) (struct super_block *sb);//在给定的超级块下创建并初始化一个新的索引节点
void (*destroy_inode) (struct inode *);//释放索引节点
void (*read_inode) (struct inode *);//以inode->i_ino为索引,从磁盘上读取索引节点
void (*dirty_inode) (struct inode *);//在索引节点被修改时调用
void (*write_inode) (struct inode *, int);//将索引节点写入磁盘,int wait参数指明写操作是否要同步
void (*put_inode) (struct inode *);//释放给定的索引节点
void (*drop_inode) (struct inode *);//在最后一个指向索引节点的引用被释放胡,VFS调用此函数
void (*delete_inode) (struct inode *);//从磁盘上删除索引节点
void (*put_super) (struct super_block *);//卸载文件系统时使用,释放超级块
void (*write_super) (struct super_block *);//更新磁盘上的超级块,对内存中的超级块和磁盘中的超级块进行同步
int (*sync_fs) (struct super_block *, int);//使文件系统的数据元和磁盘上的文件系统同步
void (*write_super_lockfs) (struct super_block *);//禁止对文件系统做改变,再更新磁盘上的超级块
void (*unlockfs) (struct super_block *);//对文件解除锁定
int (*statfs) (struct super_block *, struct statfs *);//获取文件系统状态
int (*remount_fs) (struct super_block *, int *, char *);//当指定新的安装选项重新安装文件系统时调用此函数
void (*clear_inode) (struct inode *);//释放索引节点并清空包含相关数据的所有页面
void (*umount_begin) (struct super_block *);//中断安装操作,用于网络文件系统(如NFS)
int (*show_options) (struct seq_file *, struct vfsmount *);
};
调用方法:sb->s_op->write_super(sb);
12.6 索引节点对象
包含内核在操作文件或目录时需要的全部信息。
struct inode {
struct hlist_node i_hash; /* hash list */
struct list_head i_list; /* list of inodes */
struct list_head i_dentry; /* list of dentries */
unsigned long i_ino; /* inode number */
atomic_t i_count; /* reference counter */
umode_t i_mode; /* access permissions */
unsigned int i_nlink; /* number of hard links */
uid_t i_uid; /* user id of owner */
gid_t i_gid; /* group id of owner */
kdev_t i_rdev; /* real device node */
loff_t i_size; /* file size in bytes */
struct timespec i_atime; /* last access time */
struct timespec i_mtime; /* last modify time */
struct timespec i_ctime; /* last change time */
unsigned int i_blkbits; /* block size in bits */
unsigned long i_blksize; /* block size in bytes */
unsigned long i_version; /* version number */
unsigned long i_blocks; /* file size in blocks */
unsigned short i_bytes; /* bytes consumed */
spinlock_t i_lock; /* spinlock */
struct rw_semaphore i_alloc_sem; /* nests inside of i_sem */
struct semaphore i_sem; /* inode semaphore */
struct inode_operations *i_op; /* inode ops table */
struct file_operations *i_fop; /* default inode ops */
struct super_block *i_sb; /* associated superblock */
struct file_lock *i_flock; /* file lock list */
struct address_space *i_mapping; /* associated mapping */
struct address_space i_data; /* mapping for device */
struct dquot *i_dquot[MAXQUOTAS]; /* disk quotas for inode */
struct list_head i_devices; /* list of block devices */
struct pipe_inode_info *i_pipe; /* pipe information */
struct block_device *i_bdev; /* block device driver */
unsigned long i_dnotify_mask; /* directory notify mask */
struct dnotify_struct *i_dnotify; /* dnotify */
unsigned long i_state; /* state flags */
unsigned long dirtied_when; /* first dirtying time */
unsigned int i_flags; /* filesystem flags */
unsigned char i_sock; /* is this a socket? */
atomic_t i_writecount; /* count of writers */
void *i_security; /* security module */
__u32 i_generation; /* inode version number */
union {
void *generic_ip; /* filesystem-specific info */
} u;
};
struct inode_operations {
int (*create) (struct inode *, struct dentry *,int);//为dentry对象创建新的索引节点
struct dentry * (*lookup) (struct inode *, struct dentry *);//在特定目录中寻找索引节点
int (*link) (struct dentry *, struct inode *, struct dentry *);//被系统调用link()调用,创建硬链接
int (*unlink) (struct inode *, struct dentry *);//被系统调用unlink()调用,从目录dir中删除由目录项dentry指定的索引节点对象
int (*symlink) (struct inode *, struct dentry *, const char *);//系统调用symlink(),创建符号链接
int (*mkdir) (struct inode *, struct dentry *, int);//系统调用mkdir(),创建一个新目录
int (*rmdir) (struct inode *, struct dentry *);
int (*mknod) (struct inode *, struct dentry *, int, dev_t);//系统调用mknod(),创建特殊文件
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);//移动文件
int (*readlink) (struct dentry *, char *, int);//系统调用readlink(),拷贝数据到特定的缓冲buffer中
int (*follow_link) (struct dentry *, struct nameidata *);//从一个符号链接查找它指向的索引节点
int (*put_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *);//修改文件大小
int (*permission) (struct inode *, int);//检查给定的inode所代表的文件是否允许特定的访问模式
int (*setattr) (struct dentry *, struct iattr *);//被notify_change()调用,修改索引节点后,通知发生了“改变事件”
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);//通知索引节点需要从磁盘中更新时,调用
int (*setxattr) (struct dentry *, const char *,//给dentry指定的文件设置扩展属性
const void *, size_t, int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);//向value中拷贝给定文件的扩展属性name对应的数值
ssize_t (*listxattr) (struct dentry *, char *, size_t);//将特定文件的所有属性列表拷贝到一个缓冲列表中。
int (*removexattr) (struct dentry *, const char *);//从文件中删除指定的属性
}
调用:i->i_op->truncate(i)
12.7 目录项对象
每个dentry对象代表路径中的一个特定部分。
struct dentry {
atomic_t d_count; /* usage count */
unsigned long d_vfs_flags; /* dentry cache flags */
spinlock_t d_lock; /* per-dentry lock */
struct inode *d_inode; /* associated inode */
struct list_head d_lru; /* unused list */
struct list_head d_child; /* list of dentries within */
struct list_head d_subdirs; /* subdirectories */
struct list_head d_alias; /* list of alias inodes */
unsigned long d_time; /* revalidate time */
struct dentry_operations *d_op; /* dentry operations table */
struct super_block *d_sb; /* superblock of file */
unsigned int d_flags; /* dentry flags */
int d_mounted; /* is this a mount point? */
void *d_fsdata; /* filesystem-specific data */
struct rcu_head d_rcu; /* RCU locking */
struct dcookie_struct *d_cookie; /* cookie */
struct dentry *d_parent; /* dentry object of parent */
struct qstr d_name; /* dentry name */
struct hlist_node d_hash; /* list of hash table entries */
struct hlist_head *d_bucket; /* hash bucket */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* short name */
};
VFS层遍历路径名中的所有元素并将之解析成目录项对象非常耗时 => 目录项缓存(dcache)
目录项缓存:
被使用的目录项链表——通过索引节点对象中的i-dentry项链接相关的索引节点
最近被使用的双向链表——含有未被使用和负状态的目录项对象,链头节点最新,链尾最旧
散列表和相关的散列函数——用于快速将给定路径解析为相关目录项对象
=> dcache一定程度上也提供对索引节点的缓存
struct dentry_operations {
int (*d_revalidate) (struct dentry *, int);//判断目录对象是否有效
int (*d_hash) (struct dentry *, struct qstr *);//为目录项生成散列表
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);//比较两个文件名
int (*d_delete) (struct dentry *);//当目录项对象的d_count值为0时,调用此函数
void (*d_release) (struct dentry *);//释放目录项对象
void (*d_iput) (struct dentry *, struct inode *);//当一个目录项丢失相关索引节点时调用
};
12.8 文件对象
表示进程已打开的文件。
文件对象与用户空间联系最紧密,因为进程直接处理的是文件,而不是超级块、索引节点或目录项。
由于多个进程可以同时打开和操作同一个文件,因此一个文件对应的文件对象不是唯一的,但对应的索引节点的目录项是唯一的。只有目录项对象才表示已打开的实际文件。
struct file {
struct list_head f_list; /* list of file objects */
struct dentry *f_dentry; /* associated dentry object */
struct vfsmount *f_vfsmnt; /* associated mounted fs */
struct file_operations *f_op; /* file operations table */
atomic_t f_count; /* file object's usage count */
unsigned int f_flags; /* flags specified on open */
mode_t f_mode; /* file access mode */
loff_t f_pos; /* file offset (file pointer) */
struct fown_struct f_owner; /* owner data for signals */
unsigned int f_uid; /* user's UID */
unsigned int f_gid; /* user's GID */
int f_error; /* error code */
struct file_ra_state f_ra; /* read-ahead state */
unsigned long f_version; /* version number */
void *f_security; /* security module */
void *private_data; /* tty driver hook */
struct list_head f_ep_links; /* list of eventpoll links */
spinlock_t f_ep_lock; /* eventpoll lock */
struct address_space *f_mapping; /* page cache mapping */
};
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
ssize_t (*aio_write) (struct kiocb *, const char *, size_t, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int);
int (*aio_fsync) (struct kiocb *, int);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *,
unsigned long, loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *,
unsigned long, loff_t *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t,
read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int,
size_t, loff_t *, int);
unsigned long (*get_unmapped_area) (struct file *, unsigned long,
unsigned long, unsigned long,
unsigned long);
int (*check_flags) (int flags);
int (*dir_notify) (struct file *filp, unsigned long arg);
int (*flock) (struct file *filp, int cmd, struct file_lock *fl);
};
12.9 和文件系统相关的数据结构
file_system_type——描述各种特定文件系统类型,比如ext3或XFS
每种文件系统,不管有多少个实例安装到系统中,还是根本就没安装到系统中,都只有一个file_system_type结构。
struct file_system_type {
const char *name; /* filesystem's name */
struct subsystem subsys; /* sysfs subsystem object */
int fs_flags; /* filesystem type flags */
/* the following is used to read the superblock off the disk */
struct super_block *(*get_sb) (struct file_system_type *, int,
char *, void *);
/* the following is used to terminate access to the superblock */
void (*kill_sb) (struct super_block *);
struct module *owner; /* module owning the filesystem */
struct file_system_type *next; /* next file_system_type in list */
struct list_head fs_supers; /* list of superblock objects */
};
vfsmount——当文件系统被实际安装时,在安装点创建一个vfsmount结构。
struct vfsmount {
struct list_head mnt_hash; /* hash table list */
struct vfsmount *mnt_parent; /* parent filesystem */
struct dentry *mnt_mountpoint; /* dentry of this mount point */
struct dentry *mnt_root; /* dentry of root of this fs */
struct super_block *mnt_sb; /* superblock of this filesystem */
struct list_head mnt_mounts; /* list of children */
struct list_head mnt_child; /* list of children */
atomic_t mnt_count; /* usage count */
int mnt_flags; /* mount flags */
char *mnt_devname; /* device file name */
struct list_head mnt_list; /* list of descriptors */
struct list_head mnt_fslink; /* fs-specific expiry list */
struct namespace *mnt_namespace /* associated namespace */
};
vfsmount结构还保存了安装时指定的标志信息,存储在mnt_flags域中。
Flag
Description
MNT_NOSUID
Forbids setuid and setgid flags on binaries on this filesystem
禁止该文件系统的可执行文件设置setuid和setgid标志
MNT_NODEV
Forbids access to device files on this filesystem
禁止访问该文件系统上的设备文件
MNT_NOEXEC
Forbids execution of binaries on this filesystem
禁止执行该文件系统上的可执行文件
12.10 和进程相关的数据结构
struct files_struct {
atomic_t count; /* structure's usage count */
spinlock_t file_lock; /* lock protecting this structure */
int max_fds; /* maximum number of file objects */
int max_fdset; /* maximum number of file descriptors */
int next_fd; /* next file descriptor number */
struct file **fd; /* array of all file objects */
fd_set *close_on_exec; /* file descriptors to close on exec() */
fd_set *open_fds; /* pointer to open file descriptors */
fd_set close_on_exec_init; /* initial files to close on exec() */
fd_set open_fds_init; /* initial set of file descriptors */
struct file *fd_array[NR_OPEN_DEFAULT]; /* default array of file objects */
};
,包含所有与每个进程相关的信息,如打开的文件及文件描述符等。由进程描述符的files域指向
struct fs_struct {
atomic_t count; /* structure usage count */
rwlock_t lock; /* lock protecting structure */
int umask; /* default file permissions*/
struct dentry *root; /* dentry of the root directory */
struct dentry *pwd; /* dentry of the current directory */
struct dentry *altroot; /* dentry of the alternative root */
struct vfsmount *rootmnt; /* mount object of the root directory */
struct vfsmount *pwdmnt; /* mount object of the current directory */
struct vfsmount *altrootmnt; /* mount object of the alternative root */
};
,包含当前进程的当前工作目录和根目录,由进程描述符的fs域指向
struct namespace {
atomic_t count; /* structure usage count */
struct vfsmount *root; /* mount object of root directory */
struct list_head list; /* list of mount points */
struct rw_semaphore sem; /* semaphore protecting the namespace */
};
,使得每个进程在系统中看到唯一的安装文件系统(不仅是唯一的根目录,而且是唯一的文件系统层次结构)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/85048/showart_1902509.html |
|