前一段时间研究了一下romfs文件系统,现就此小结一下。
不管什么样的文件系统,在内存中都是dentry和inode结构,打开一个文件F,实际上就是要在内存中建立F的dentry和inode结构,并让他们的结构连系起来。
所谓"文件",
就是按一定的形式存储在介质上的信息,所以一个文件其实包含了两方面的信息,一是存储的数据本身,二是有关该文件的组织和管理的信息。在内存中,
每个文件都有一个dentry(目录项)和inode(索引节点)结构,dentry记录着文件名,上级目录等信息,正是它形成了我们所看到的树状结构;
而有关该文件的组织和管理的信息主要存放inode里面,它记录着文件在存储介质上的位置与分布。同时dentry->d_inode指向相应的
inode结构。dentry与inode是多对一的关系,
一 .索引节点(inode)
inode:inode包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间等信息。它是linux管理文件系统的最基本单位,也是文件系统连接任何子目录、文件的桥梁。
struct inode {
struct hlist_node i_hash; /* 哈希表 */
struct list_head i_list; /* 索引节点链表 */
struct list_head i_dentry; /* 目录项链表 */ unsigned long i_ino; /* 节点号 */
atomic_t i_count; /* 引用记数 当前使用该结点的进程数 */
umode_t i_mode; /* 访问权限控制 */
unsigned int i_nlink; /* 硬链接数 */
uid_t i_uid; /* 使用者id */
gid_t i_gid; /* 使用者id组 */
kdev_t i_rdev; /* 实设备标识符 */
loff_t i_size; /* 以字节为单位的文件大小 */
struct timespec i_atime; /* 最后访问时间 */
struct timespec i_mtime; /* 最后修改(modify)时间 */
struct timespec i_ctime; /* 最后改变(change)时间 */
unsigned int i_blkbits; /* 以位为单位的块大小 */
unsigned long i_blksize; /* 以字节为单位的块大小 */
unsigned long i_version; /* 版本号 */
unsigned long i_blocks; /* 文件的块数 */
unsigned short i_bytes; /* 使用的字节数 */
spinlock_t i_lock; /* 自旋锁 */
struct rw_semaphore i_alloc_sem; /* 索引节点信号量 */
struct inode_operations *i_op; /* 索引节点操作表 */
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; /* 设备地址映射 */
struct dquot *i_dquot[MAXQUOTAS]; /* 节点的磁盘限额 */
struct list_head i_devices; /* 块设备链表 */
struct pipe_inode_info *i_pipe; /* 管道信息 */
struct block_device *i_bdev; /* 块设备驱动 */
unsigned long i_dnotify_mask; /* 目录通知掩码 */
struct dnotify_struct *i_dnotify; /* 目录通知 */
unsigned long i_state; /* 状态标志 */
unsigned long dirtied_when; /* 首次修改时间 */
unsigned int i_flags; /* 文件系统标志 */
unsigned char i_sock; /* 可能是个套接字吧 */
atomic_t i_writecount; /* 写者记数 */
void *i_security; /* 安全模块 */
__u32 i_generation; /* 索引节点版本号 */
union {
void *generic_ip; /* 文件特殊信息 */
} u;
};
二.目录项(dentry)
目录项(dentry):包含文件名,文件属性结构,磁盘地址等文件属性信息,一个索引节点包含多个目录项。
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; 未使用链表的指针
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; /* used by d_revalidate */
struct dentry_operations *d_op; 目录项方法
struct super_block * d_sb; 文件的超级块对象
vunsigned long d_vfs_flags;
void * d_fsdata;与文件系统相关的数据
unsigned char d_iname [DNAME_INLINE_LEN]; 存放短文件名
};
2> dentry与inode
inode(可理解为ext2 inode)对应于物理磁盘上的具体对象,dentry是一个内存实体,其中的d_inode成员指向对应的inode。也就是说,一个inode可以在运行的时候链接多个dentry,而d_count记录了这个链接的数量。
在inode结构中有一个双向链表struct list_head i_dentry结构,这个链表链接“被使用的”目录项,当然,这些目录项的d_inode指针都指向同一个inode结构。这代表什么呢?表示一个索引节点可以对应多个目录项对象。
3>如何查找文件?(说比较大)
每个文件都对应一个inode,当查找文件时,会使用哈希函数先从目录项缓存中找,以/user/lxy/1.c 为例,它会从右1.c开始,从右向左开始查找到根目录,如果找不到,会先找到根目录,从根目录开始逐级查找。先找到根目录的dentry,dentry结构体中有一个d_inode(存有与文件名相关的索引节点),利用它再找到/对应的inode,inode结构体里面有一个i_dentry,i_dentry记录了所有的下一级目录项,若找到,则会在inode中找到对应的文件信息,否则,在会指向下一个dentry,依次查找。。。
4>一个索引节点对应多个目录项对象,其实现会用到软硬链接。
硬链接:链接对象拥有相同的inode,因为二者对应于硬盘中的具体对象相同。但是链接对象与被链接对象,其内容相同。且删除其中一个对另一个没有影响,仍然可以产看文件内容,相当于文件复制。
命令: ln a b。
软链接(符号链接):链接对象的inode不同,创建成功后二者内容相同,但当删除被链接文件时,链接文件无法打开。类似于windows中的快捷方式。
命令: ln -s a b
故,一个索引节点对应多个目录项和硬链接很像。