宅男
分类: LINUX
2012-12-07 21:49:02
最近准备写一个系列的博文,来简单的介绍一下怎么去写一个简单的文件系统。
我们通常很华丽的在Linux shell中输入一行命令来挂载一个文件系统,这样所有的进程都可以访问这些存储在物理介质中的数据了。比如:
Mount –t vfat /dev/block/mmcblk1p1 /mnt/fat
-t用来指定所挂载的文件系统的类型,Linux一大优点就是对文件系统兼容度比较高。
既然要挂载一个文件系统,首先操作系统需要对该文件系统。这个工作通常是由Linux中的
register_filesystem函数来完成的。比如:
static int __init init_myfs(void)
{
int error = 0;
printk("myfs init\n");
error = register_filesystem(&myfs_fs_type);
if(error)
printk("register myfs failed \n");
return error;
}
static void __exit exit_myfs(void)
{
printk("myfs removing \n");
unregister_filesystem(&myfs_fs_type);
}
其实Linux系统中维护了一个file_system_type类型的链表,每一个注册的文件系统类型都被添加到这样一个链表中去。所以mount的时候,可以很轻松的辨别出是否是操作系统所支持的文件系统类型。
static struct file_system_type myfs_fs_type = {
.owner = THIS_MODULE,
.name = "myfs",
.mount = myfs_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
这边定义了一个myfs_fs_type,注意其中的一些初始化的结构体字段。毫无疑问 name就是这个文件系统的名称,也就是我们mount时候-t所指定的名称。myfs_mount用于在挂载的时候被调用,kill_block_super用于文件系统卸载(unmount)的时候被调用。FS_REQUIRES_DEV用于指定该文件系统不是一个虚拟的文件系统,需要依赖于物理的存储介质。
好了,这样一个简单的文件系统就注册成功了。
struct dentry *myfs_mount(struct file_system_type *fs, int flags,const char *dev_name, void *data)
{
/*ignore the dev_name*/
printk("myfs_mount \n");
return mount_bdev(fs, flags,dev_name, data,myfs_fill_super);
}
myfs_mount用于挂载的时候被调用,注意这儿的参数fs, flags,dev_name, data都是从虚拟文件系统VFS传递过来的,所以不需要理会,注意这样的myfs_fill_super函数,是用于mount过程中从存储介质中读出超级块super_block ,关于什么是超级块,这样简单的说明一些,超级块相当于文件系统的一张身份证,记录了文件系统的一些概括性的信息,比如文件系统中有多少文件,这个文件系统容量有多大,剩余多少空闲空间等等。虚拟文件系统层对于文件系统的兼容性做了一定的规定,比如struct super_block。不管你文件系统内部是如何管理信息的,但是在mount的时候必须填充一个super_block信息交给VFS层,而每一个文件系统的fill_superblock函数都不一样,所以这儿在mount中传递了一个myfs_fill_super函数,用于本文件系统填充superblock。所以Linux才能够兼容那么多的文件系统,都是拜这层虚拟文件系统所赐。