本文转载自: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 \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文件:
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”两个目录。同时里面又有对应的文件。