话说文件系统——一个简单的文件系统(一)

  linux的文件系统很庞大,之前看过、学过、哭过、也闹过,差点就撒娇了,哎,只怪功底不够,硬是没有看明白,心想小僧此生与它无缘了,

又无高人,迷津终没有得到指点。时间就这么平静而有飞逝着,突然有一天无意当中看到一本叫

《linux内核探秘:深入解析文件系统和设备驱动的框架与设计》书,里面有一个最简单的文件系统(aufs)的实现,又激起我研究linux文件系统

的欲望。发现aufs的实现仅仅有两百多行,正由于它的简单,分析起来容易,同时也涉及到了linux文件系统的各个方面,分析之后,对文件系统

的基本概念有了最基本的认识,为后面的学习打下了基础,在此把整个学习的过程做个记录,如果对大家有帮助,我就很荣幸了。

  回顾来看,其实之前没有弄明白的主要原因在于着急,没有从基础的、简单的开始,一上来就直接看源代码,分析sysfs这些成熟的文件系统,

由于sysfs本身跟其他的东西错综盘旋在一起,增加了很多的难度,这样连续几天就会失去学习的信心,从而放弃,所谓心急吃不了热豆腐,欲速

则不达啊。正因为此,我们最开始先看一下aufs的实现,自己编译一波,感受一下,有个感性的认识,而不一上来就讲原理,我们要循序渐进,

下面就是aufs的实现。

aufs文件系统的实现源码:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/cred.h>
#include <linux/mount.h>

//每个文件系统需要一个MAGIC number #define AUFS_MAGIC 0x64668735 //aufs文件系统的挂载点 static struct vfsmount *aufs_mount; //根据创建的aufs文件系统的 super_block创建具体的inode结构体 static struct inode *aufs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode *inode = new_inode(sb); if (inode) { inode->i_mode = mode; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); inode->i_blocks = 0; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); break; case S_IFREG: printk("create a file \n"); break; case S_IFDIR: inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; printk("creat a dir file \n"); inode->__i_nlink++; break; } } return inode; } //把创建的inode和dentry结构体连接起来 static int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) { struct inode * inode; int error = -EPERM; if (dentry->d_inode) return -EEXIST; inode = aufs_get_inode(dir->i_sb, mode, dev); if (inode) { d_instantiate(dentry, inode); dget(dentry); error = 0; } return error; } static int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { int res; res = aufs_mknod(dir, dentry, mode | S_IFDIR, 0); if (!res) { dir->__i_nlink++; } return res; } static int aufs_create(struct inode *dir, struct dentry *dentry, int mode) { return aufs_mknod(dir, dentry, mode | S_IFREG, 0); } //根据父dentry、mode、name创建子dentry static int aufs_create_by_name(const char *name, mode_t mode, struct dentry *parent, struct dentry **dentry) { int error = 0; if (!parent) { if (aufs_mount && aufs_mount->mnt_sb) { parent = aufs_mount->mnt_sb->s_root; } } if (!parent) { printk("Ah! can not find a parent!\n"); return -EFAULT; } *dentry = NULL; mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(dentry)) { if ((mode & S_IFMT) == S_IFDIR) error = aufs_mkdir(parent->d_inode, *dentry, mode); else error = aufs_create(parent->d_inode, *dentry, mode); } else error = PTR_ERR(dentry); mutex_unlock(&parent->d_inode->i_mutex); return error; } //在aufs文件系统中创建文件 struct dentry *aufs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data, struct file_operations *fops) { struct dentry *dentry = NULL; int error; printk("aufs: creating file '%s'", name); error = aufs_create_by_name(name, mode, parent, &dentry); if (error) { dentry = NULL; goto exit; } if (dentry->d_inode) { if (data) dentry->d_inode->i_private = data; if (fops) dentry->d_inode->i_fop = fops; } exit: return dentry; } //在aufs文件系统中创建一个文件夹 struct dentry *aufs_create_dir(const char *name, struct dentry *parent) { return aufs_create_file(name, S_IFDIR | S_IRWXU | S_IRUGO, parent, NULL, NULL); } static int enabled = 1; //对应于打开的aufs文件的读取方法 static ssize_t aufs_file_read(struct file *fle, char __user *buf, size_t nbytes, loff_t *ppos) { char *s = enabled ? "aufs read enabled\n" : "aufs read disabled\n"; dump_stack(); return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s)); } //对应于打开的aufs文件的写入方法 static ssize_t aufs_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { int res = *buffer - '0'; if (res) enabled = 1; else enabled = 0; return count; } //对应具体打开文件的文件操作方式 static struct file_operations aufs_file_operations = { .read = aufs_file_read, .write = aufs_file_write, }; //用于填充aufs的super_block static int aufs_fill_super(struct super_block *sb, void *data, int silent) { static struct tree_descr debug_files[] = {{""}}; return simple_fill_super(sb, AUFS_MAGIC, debug_files); } //创建aufs文件系统的对应的根目录的dentry static struct dentry *aufs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_single(fs_type, flags, data, aufs_fill_super); } //初始化aufs文件系统的 file_system_type结构,每个文件系统对应一个这样的结构体,主要用于提供具体文件系统的
//的信息,以及操作的方法 static struct file_system_type aufs_type = { .name = "aufs", .mount = aufs_get_sb, .kill_sb = kill_litter_super, }; //创建aufs文件系统,同时创建对应的文件夹和文件 static int __init aufs_init(void) { int ret; struct dentry *pslot; ret = register_filesystem(&aufs_type); if (ret) { printk(KERN_ERR "aufs: cannot register file system\n"); return ret; } aufs_mount = kern_mount(&aufs_type); if (IS_ERR(aufs_mount)) { printk(KERN_ERR "aufs: cannot mount file system\n"); unregister_filesystem(&aufs_type); return ret; } pslot = aufs_create_dir("woman_star", NULL); //创建woman_star文件系统,返回所创建文件夹的dentry aufs_create_file("lbb", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations);//在对应的文件夹下,创建具体的文件 aufs_create_file("fbb", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations); aufs_create_file("lj1", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations); pslot = aufs_create_dir("man_star", NULL); aufs_create_file("ldh", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations); aufs_create_file("lcw", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations); aufs_create_file("jw", S_IFREG | S_IRUGO, pslot, NULL, &aufs_file_operations); return 0; } //卸载aufs文件系统 static void __exit aufs_exit(void) { kern_unmount(aufs_mount); unregister_filesystem(&aufs_type); aufs_mount = NULL; } module_init(aufs_init); module_exit(aufs_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("This is a simple module"); MODULE_VERSION("Ver 0.1");

 

下面编译的Makefile文件:

ifneq ($(KERNELRELEASE),)
obj-m := aufs.o
else
KDIR := /lib/modules/$(shell uname -r)/build
all:
	make -C $(KDIR) M=$(shell pwd) modules
clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order
endif

 程序编译后,我们通过insmod 命令加载模块,然后执行如下操作。

1.在根目录下创建一个目录:

mkdir aufs

2. 挂载文件系统:

mount -t aufs none aufs/

3. 列出文件系统的内容:

ls

通过查看看到了“woman_star”和“man_star”两个目录。同时里面又有对应的文件。

posted @ 2018-04-14 17:01  葡萄宝宝  阅读(1306)  评论(0编辑  收藏  举报