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

本文转载自:https://www.cnblogs.com/xie0812/articles/8832881.html

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

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

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

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

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

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

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

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

下面就是aufs的实现。

aufs文件系统的实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#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 ");
                break;
            case S_IFDIR:
                inode->i_op = &simple_dir_inode_operations;
                inode->i_fop = &simple_dir_operations;
                printk("creat a dir file ");
                 
                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! ");
        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 " "aufs read disabled ";
    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 ");
        return ret;
    }
 
    aufs_mount = kern_mount(&aufs_type);
    if (IS_ERR(aufs_mount)) {
        printk(KERN_ERR "aufs: cannot mount file system ");
        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文件:

1
2
3
4
5
6
7
8
9
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”两个目录。同时里面又有对应的文件。

原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/9024202.html