目录项对象:
每个文件除了有一个索引节点inode数据结构外,还有一个目录项dentry数据结构。dentry结构中有个d_inode指针指向相应的inode结构。大家有没有想过。既然inode结构和dentry结构都是对文件各方面属性的描述,为什么不直接把两个结构合二为一呢?这是因为目录项结构描述的是文件逻辑上的属性,在磁盘上并没有对应的映像,因此在dentry结构中不包含指出该对象已被修改的字段。目录项对象存放在名为dentry_cache的slab分配器高速缓存中;而indode结构代表的是物理意义上的文件,记录的是物理上的属性,对于一个具体的文件系统,如Ext2,Ext2_inode结构在磁盘上就有对应的映像。所以说,一个索引节点对象可能对应多个目录项对象。而一个目录项对象只能对应一个索引节点。也就是说,一个文件可以有不止一个文件名或路径名。这是因为一个应经建立的文件可以被Link到其他文件名。所以在inode结构中有一个队列i_dentry,凡是代表着同一个文件的所有目录项都通过其dentry结构中的d_alias域挂入相应inode结构中的i_dentry队列。
一旦目录项被读入内存,VFS就把他转换成基于dentry结构的一个目录项对象,对于进程查找路径名中的每个分量,内核都为其创建一个目录项对象;目录项对象将每个分量与其对应的索引结点相联系。例如:在查找路径名/proc/syskall时,内核为根目录“/”创建一个目录项对象,为根目录下的proc项创建一个第二级目录对象,为/proc目录下的test项创建一个第三级目录项对象。
- struct dentry {
- unsigned int d_flags; 目录项高速缓存标志
- struct dentry *d_parent; 父目录的目录项对象
- struct qstr d_name; 文件名
- struct inode *d_inode; 与文件名关联的索引结点
- unsigned char d_iname[DNAME_INLINE_LEN]; 短文件名
- spinlock_t d_lock; 保护目录项的自旋锁
- const struct dentry_operations *d_op; 操作目录项的函数
- struct super_block *d_sb; 目录项树的根(即文件的超级块)
- struct list_head d_lru; 未使用的LRU链表
- struct list_head d_subdirs; 该目录项的子目录所形成的链表
- struct list_head d_alias; 索引结点别名的链表。
- .....
- };
一个文件系统中所有目录项结构一般会组织为一个哈希表,或者组织为一棵树,或者按照某种需要组织为一个链表,这是为文件访问和文件路径搜索奠定下良好的基础。对目录项操作的一组函数叫目录项操作表。d_revalidata:判断目录项是否生效。
d_hash():生成一个哈希值。
d_compare():比较两个文件名。
d_delete():删除d_count域为0的目录项对象。
d_release():释放一个目录项对象。
d_input():调用该方法丢弃目录项对应的索引结点。
文件对象
文件对象是已打开文件在内存中的表示,因此,它在磁盘上并没有与之对应的数据。也就是说,文件对象只存在于内存中,所以这个结构也就不涉及脏数据字段和是否需要写回磁盘。
文件最终是要被进程访问的,一个进程可以打开多个文件,而一个文件可以被多个进程同时访问。每个打开的文件都用一个32位的数字来表示下一个读写的字节位置,这个数字叫做文间位置或偏移量。可以通过执行系统调用lseek对文件位置进行修改。Linux在file文件对象中保存了打来文件的文件位置,这个对象称为打开的文件描述符。
大家可能会产生疑惑,为什么不把文件位置存放在inode中呢?原因是Linux文件是共享的,加入把文件位置放在索引结点中,则如果有两个或更多的进程同时打开同一个文件,他们将去访问同一个索引结点,于是一个进程的lseek操作将影响到另一个进程的读操作,这显然是不可想象的。
- struct file {
- struct list_head f_list; 所有打开的文件形成的链表
- struct dentry *f_dentry; 与文件相关的目录项对象
- struct vfsmount *f_vfsmnt; 该文件所在的已安装的文件系统
- struct file_operations *f_op; 指向文件操作表的指针
- unsigned int f_flags; 打开文件时所指定的标志
- fmode_t f_mode; 文件的打开模式
- loff_t f_pos; 文件的当前位置
- ......
- };
对文件操作的一组函数叫文件操作表。由file_operations结构描述:llseek();修改文件指针
read():从文件中读出若干字节。
write():给文件中写若干字节。
mmap():文件到内存的映射。
open():打开文件。
flush():关闭文件时减少f_count的计数。
fsync():文件在缓冲区的数据写回磁盘。
fs_struct结构描述进程与文件系统的关系,该函数在include/linux/fs_struct.h中定义。
- struct fs_struct {
- int users;
- spinlock_t lock;
- seqcount_t seq;
- int umask;
- int in_exec;
- struct path root, pwd; root为根目录,pwd指向进程当前所在的目录。
- };
阅读(1871) | 评论(0) | 转发(0) |