前文简单介绍了block device和device mapper。有了这两个基础,再来看flashcache的代码,就容易理解多了。Flashcache是一个内核模块,要更清晰的理解代码,还需要了解一下内核模块编写的一些基础知识。好吧,虽然对于内核编程我完全是个门外汉,这里还是需要现学现卖下。所以这一篇还是不会切入正题,已经熟悉Linux内核模块的同学请忽略并耐心等待。
Linux内核支持动态的加载模块(Loadable Kernel Module,LKM)以完成某些特定的功能,模块编程需要按照一定的格式以便可以和内核交互。
5. 内核符号表
内核模块之间的交互需要通过特定的共享变量和函数,这些都需要输出到内核符号表。在模块编程中使用EXPORT_SYMBOL来进行定义。在内核中则使用了kernel_symbol结构来保存符号表信息。
# 内核编程基本上都需要包含如下三个头文件。 #includekernel.h> #include<linux module.h> #includeinit.h> #内核符号表结构体 struct kernel_symbol { unsigned long value; #函数地址 const char *name; #函数名 }; # 导出符号的宏定义 #define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "") #define __EXPORT_SYMBOL(sym, sec) \ extern typeof(sym) sym; \ __CRC_SYMBOL(sym, sec) \ static const char __kstrtab_##sym[] \ __attribute__((section("__ksymtab_strings"), aligned(1))) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __ksymtab_##sym \ __used \ __attribute__((section("__ksymtab" sec), unused)) \ = { (unsigned long)&sym, __kstrtab_##sym } < pre>输出的符号表可以在/proc/kallsyms查看到。
6. 模块入口/退出函数
一般的c程序的入口函数是main,但模块的入口函数是module_init,退出函数则是module_exit。当内核启动或者执行insmod时执行module_init定义的函数,到内核关闭或者rmmod时执行module_exit定义的函数。
#define module_init(x) __initcall(x); #define module_exit(x) __exitcall(x);
当然,还有一些宏定义了模块的一些信息,如
MODULE_AUTHOR
MODULE_DESCRIPTION
MODULE_ALIAS
MODULE_LICENSE
MODULE_PARM_DESC
7. 内存分配
内核中不能使用用户空间的malloc()和free()来分配/回收内存。而需要使用内核空间的内存分配/回收工作,常用的有kmalloc/kfree,基于slab内存分配算法:
void *kmalloc(size_t size, gfp_t flags) void kfree(const void *objp)
对于slab内存分配器,这里不再详细展开。通过/proc/slabinfo或者slabtop可以查看slab内存分配的一些情况。
另外,在内核中也不能使用用户态的printf来输出信息,而需要使用内核态的printk。
8. 模块工具
8.1 insmod
Linux模块编译好以后一般是.ko文件,通过执行insmod可以将编译好的模块加载到内核中。在装载内核模块时,用户可以向模块传递一些参数:
$ sudo insmod mod_name var=key
8.2 rmmod
rmmod则用来卸载已经加载到内核的模块
$sudo rmmod mod_name
8.3 lsmod
lsmod可以列出已经加载到内核中的模块
lsmod Module Size Used by nf_conntrack_ipv6 8785 1 aes_i586 7244 2 aes_generic 26755 1 aes_i586 ipt_MASQUERADE 1315 0 xt_state 930 2 ...
也可以通过/proc/modules来获取内核模块列表。
8.4 modinfo
查看某个模块的信息
$ modinfo raid0 filename: /lib/modules/2.6.36-ningoo/kernel/drivers/md/raid0.ko alias: md-level-0 alias: md-raid0 alias: md-personality-2 description: RAID0 (striping) personality for MD license: GPL srcversion: 2CFE19548162CD6E80EE58B depends: vermagic: 2.6.36-ningoo SMP mod_unload modversions CORE2
8.5 modprobe
modprobe是一个比较强大的工具,既可以列出已经安装的模块信息,也可以用来加载/卸载模块,并且能够处理同时将依赖的模块自动进行加载。
$ modprobe -l $ sudo modprobe -r mod_name $ sudo modprobe mod_name
/etc/modprobe.conf和/etc/modprobe.d/保存了一些modprobe可能用到的配置。
未完待续
参考:
[1] 2.6内核模块编程实例指导
[2] 小白学Linux之内核模块编程
您可能也喜欢: |
深入浅出Flashcache(四) |
SSD硬盘时代即将到来? |
SSD硬盘的IO性能测试 |
Linux上eclipse本地跑web应用绑定80端口的问题 |
在64位Linux上安装MemCached |
无觅 |