一、实验
查看变量 super_blocks、sb_lock 的地址:
对代码进行修改,super_block.c 代码如下:
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/init.h>
#include<linux/list.h>
#include<linux/spinlock.h>
#include<linux/kdev_t.h>
#define SUPER_BLOCKS_ADDRESS 0xffffffff940ff2b0
#define SB_LOCK_ADDRESS 0xffffffff9470ee98
static int __init my_init(void)
{
struct super_block *sb;
struct list_head *pos;
struct list_head *linode;
struct inode *pinode;
unsigned long long count = 0;
printk("\nPrint some fields of super_blocks:\n");
spin_lock((spinlock_t *)SB_LOCK_ADDRESS); //加锁
list_for_each(pos, (struct list_head *)SUPER_BLOCKS_ADDRESS) {
sb = list_entry(pos, struct super_block, s_list);
printk("dev_t: %d : %d", MAJOR(sb->s_dev), MINOR(sb->s_dev)); //打印文件系统所在设备的主设备号和次设备号
printk(" file_type name: %s\n",sb->s_type->name); //打印文件系统名
list_for_each(linode, &sb->s_inodes) {
pinode=list_entry(linode,struct inode,i_sb_list);
count++;
printk(" %lu\t",pinode->i_ino); //打印索引节点号
}
}
spin_unlock((spinlock_t *)SB_LOCK_ADDRESS); //开锁
printk("The number of inodes: %llu\n",sizeof(struct inode) *count);
return 0;
}
static void __exit my_exit(void)
{
printk("unloading...\n");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
运行结果:
二、问答
1. mount机制与超级块是什么关系,与文件系统的类型又是什么关系?
将一个文件系统的顶层目录挂到另一个文件系统的子目录上,使他们成为一个整体,称为”mount(安装)”,linux内核采用VFS框架来组织文件系统,每个文件系统用一个超级块(super_block)数据结构来描述,每个注册的文件系统,对应着相应的超级块对象。
若两个都为xfs文件系统,则xfs的file_system_type的fs_supers把两个同为xfs文件系统的super_block串连在自己下面。另一个minix文件系统没挂载使用,所以没他的super_block信息被读入内存。一个文件系统对应一个super_block,所以同一个文件系统当然只有一个super_block。但是因为挂载了两次,所有每一次挂载对应一个挂载实例struct mount,也就是有两个mount实例。
2. inode是如何分配的?磁盘inode和内存inode有什么区别?
linux文件系统使用索引节点来记录文件信息,系统给每个索引节点分配一个号码。Linux采用一种叫做Orlov allocator的算法来负责选择inode的位置。在linux中,文件的内容和属性是分离的,inode用来保存文件属性的结构。通常情况,一个文件一个inode,一个inode号。操作任何一个文件都是在特定目录下查找的,目录也是文件,所以目录里存放的是目录下所有文件的文件名和inode的映射关系。尽可能使得一个文件的数据和其inode在相同的块组中,这种方法减少了data寻址耗时,特别是刚刚读取inode后就访问数据这种场景。
磁盘inode和内存inode的区别:
(1)内存中的inode: VFS inode包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改时间等信息。磁盘上的inode:EXT2通过使用inode来定义文件系统的结构以及描述系统中每个文件的管理信息,每个文件都有一个inode且只有一个,即使文件中没有数据,其索引结点也是存在的。
(2)位置:VFS inode结构位于内存中,而Ext2_inode位于磁盘。
(3)生存期:VFS inode在需要时才会被建立,如果系统断电,此结构也随之消失。而Ext2_inode的存在与系统是否上电无关,而且无论文件是否包含数据,Ext2_inode都是存在的。
(4)唯一性:两者在自己的作用域中都是唯一的。
(5)关系:VFS inode是Ext2 inode的抽象、映射与扩充,而后者是前者的静态信息部分,也是对前者的具体化、实例化和持久化。
(6)操作:对VFS inode的操作具有通用性,对文件系统inode的操作则是文件系统相关的,依赖于特定的实现。
(7)组织管理:系统通过VFS inode链表来对其进行组织,并且为了提高访问效率相应地构造了inode构造缓存和hash table。Ext2 inode的信息位于EXT2文件系统的划分的块组中,在每个块组中包含相应的inode位图、inode表指定具体的inode信息,每个inode对应Ext2_inode结构。
3. 有了inode,为什么还要dentry? 如果没有denrty,会出现什么情况?
所谓"文件", 就是按一定的形式存储在介质上的信息,所以一个文件其实包含了两方面的信息,一是存储的数据本身,二是有关该文件的组织和管理的信息。内存中,每个文件都有dentry(目录项)和inode(索引节点)结构,dentry记录着文件名,上级目录等信息,正是它形成了我们所看到的树状结构;该文件的组织和管理的信息主要存放inode里面,它记录着文件在存储介质上的位置与分布。
因为有可能一个文件有好几个文件名,所以有inode,还要有dentry,dentry与inode是多对一的关系。
如果没有dentry可能会出现的情况是,根据inode找到了文件位置,但不知道其文件名、上级目录等信息。
4. files_struct结构和file结构是什么关系,如果没有file结构是否可以?
files_struct结构和file结构的关系如下图:
没有file结构的话就无法记录文件和进程交互的信息以及一些文件操作,将file对象f_op指向了所属文件系统的操作函数集file_operations,而该函数集又来自具体文件的inode,于是虚拟文件系统就与实际文件系统的操作就衔接起来了。
5.为什么要有一个fs_strcut结构?
如上图,fs字段指向fs_struct结构体,是用来记录这个进程的工作目录pwd,和它的根目录root, 每个进程都有自己的根目录和当前工作目录,fs_struct来记录这些信息。显然目录信息是由dentry结构体保存的;在linux中,目录也是一种文件,因此dentry结构体会有指向inode结构体的指针字段d_inode。