技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> 深入浅出Flashcache(三)

深入浅出Flashcache(三)

浏览:2006次  出处信息

    前文简单介绍了block devicedevice mapper。有了这两个基础,再来看flashcache的代码,就容易理解多了。Flashcache是一个内核模块,要更清晰的理解代码,还需要了解一下内核模块编写的一些基础知识。好吧,虽然对于内核编程我完全是个门外汉,这里还是需要现学现卖下。所以这一篇还是不会切入正题,已经熟悉Linux内核模块的同学请忽略并耐心等待。

    Linux内核支持动态的加载模块(Loadable Kernel Module,LKM)以完成某些特定的功能,模块编程需要按照一定的格式以便可以和内核交互。

    5. 内核符号表

    内核模块之间的交互需要通过特定的共享变量和函数,这些都需要输出到内核符号表。在模块编程中使用EXPORT_SYMBOL来进行定义。在内核中则使用了kernel_symbol结构来保存符号表信息。

# 内核编程基本上都需要包含如下三个头文件。
#include
#include
#include

#内核符号表结构体
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 }

    输出的符号表可以在/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则用来卸载已经加载到内核的模块

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之内核模块编程

建议继续学习:

  1. Ubuntu工作机使用FlashCache技术加速    (阅读:5229)
  2. 深入浅出Flashcache(一)    (阅读:2406)
  3. 深入浅出Flashcache(五)    (阅读:1888)
  4. 深入浅出Flashcache(二)    (阅读:1852)
  5. 深入浅出Flashcache(四)    (阅读:1850)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1