2015年(9)
分类: LINUX
2015-06-17 14:58:49
jbd2所以的文件在linux-kernel(2.6.30,我所用的是kernel2.6.30)/fs/jbd2目录下,当然还有一个文件在/include/linux下的jbd2.h。
下面来看看这个模块一共多少代码,
lan@lan-laptop:~/linux-2.6.30/fs/jbd2$ wc -l *.c
760 checkpoint.c
1066 commit.c
2383 journal.c
745 recovery.c
714 revoke.c
2180 transaction.c
7848 total
就七千多行代码,这相对于有1000多万行的linux内核来说,真是让我们做梦能笑出声来。其它的先不管,按照fudan_abc的说法,先看看Makefile文件。
lan@lan-laptop:~/linux-2.6.30/fs/jbd2$ cat Makefile
#
# Makefile for the linux journaling routines.
#
obj-$(CONFIG_JBD2) += jbd2.o
jbd2-objs := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o
除了注释就两行有用的:
obj-$(CONFIG_JBD2) += jbd2.o这行的意思是你要将jbd2模块以什么样的方式编译到内核中,有三种选择方式(Y与内核一起编译,M以模块方式编译,N不编译,当内核有Ext4或是OCFS2文件系统时不能没有jbd2)。
jbd2-objs := transaction.o commit.o recovery.o checkpoint.o revoke.o journal.o
这行的意思是jbd2所需的目标文件,一共有六个文件,这是一个make的隐式规则,这六个.o文件对应该的是同名的.c文件,就是刚才统计行数的那六个文件。当然还有一个jbd2.h在include/linux目录下,是其它(Ext4等模块)用的。
Jbd2模块的入口在journal.c文件里,看最后三行,
MODULE_LICENSE("GPL");
module_init(journal_init);
module_exit(journal_exit);
写过Linux内核驱动,哪怕是最简单的经典的printk(“hello world\n”);都知道这是三行意思。module_init(journal_init)这个表示jbd2这个模块的入口,它通过执行journal_init这个函数来实现,module_exit(journal_exit)表示这个jbd2这个模块卸载时要执行的函数journal_exit.
看journal.c的第2352行。
|
所有的模块入口函数都是一个模样,哈哈,连空行也就12行,让我们一行一行的看。
2356行是判断journal_superblock_s这个结构体的大小是不是1024字节,如果不是,则迫使编译器报一个编译错误。journal_superblock_s在include/linux/jbd2.h里,定义如下(209行开始)
|
正好是0x400=1024字节,如果不等于1024字节,那当然就出错了。接下来调用了一个journal_init_caches(),这个函数所做功能就是初化jbd2所需要的cache,这里先放下,以后再慢慢说,不管怎么样,这个函数如果成功就反回0,否返回非0,一般是负数,当然也有些函数不是返回0表示成功,而是返回一个有效的指针地址;还有一些十分变态的函数,返回非0表示成功,等遇到这样的函数我再狠狠的骂它一顿。
如果journal_init_caches()返回0,那就执行 jbd2_create_debugfs_entry()和jbd2_create_jbd_stats_proc_entry()当然,在release版本中,jbd2_create_debugfs_entry()是一个空函数,它只是为了调试用的,一调试完成,它也就没有用了,卸磨杀驴不是很多人惯用的招数么?那么jbd2_create_jbd_stats_proc_entry()又做的是什么呢?我们还是来看看它的代码(journal.c/2285)
|
一看它的名字都能知道,其实它是在linux系统里的/proc/fs创建一个目录叫jbd2.如果你的系统有分区是ext4系统,那么就会看到
lan@lan-laptop:~$ ls /proc/fs
ext4 jbd2 nfsd
那个jbd2目录就是这个函数的功劳。这里也能看到jbd2_remove_jbd_stats_proc_entry(void)这个函数,它就负责把这目录在jbd2卸载的时候把这个目录删除的,同时你也看到#ifdef CONFIG_PROC_FS这个宏,这个宏开表示我们的系统要/proc这个文件系统,如果没有开,那么就不会有/proc这个目录,更不会有fs/jbd2,所以在#else后的函数是空实现。
如果journal_init_caches()返回一个非0,就会执行jbd2_journal_destroy_caches();
来清除(可能)已经创建的cache.然后把ret返回,因为是非0,所以系统就知道这个模块在初始化的时候出错,就不会把模块调起来。