内核模块设计

Posted on 2015-02-16 17:24  Bumble_Bee  阅读(231)  评论(0编辑  收藏  举报

 一、关于内核模块
  如果将所有的组件全部编入内核映像太浪费内存空间。比方说USB驱动,我只需要它运行1分钟,那么在剩余内核运行的59分钟都没有使用到它,但是他却一直占用着系统资源,显然这很不科学,所以就有了今天的题目——内核模块设计。
  内核模块特点:
    1、不被编译进内核文件
    2、在内核运行期间可动态的运行或卸载。
    3、命令:insmod安装、lsmod查看已安装模块、rmmod卸载内核模块。
    例:内核模块:helloworld.ko,安装:insmod helloworld.ko、卸载:rmmod helloworld(注意卸载时不加.ko)
二、Linux内核模块设计
  1、内核模块的编写
  首先看一段内核模块范例代码  

#include <linux/init.h>
#include <linux/module.h>


static int hello_init()
{
    printk("Helloworld\n");
    return 0;
}

static void hello_exit()
{
    printk("Good Bye\n");
}

module_init(hello_init);
module_exit(hello_exit);

  可以看到这段c程序没有main函数。main函数对一段应用程序来说是一个入口,那么没有main函数就没有入口了吗?显然不是。内核模块有三个要素, 头文件、module_init、module_exit。头文件很简单不用说,module_init就是这段程序的入口。当insmod这个内核模块 时,系统就会调用module_init宏指明的函数,也就是这里的hello_init函数。同样,module_exit就是这段程序的出口,当 rmmod这个模块的时候,系统就会调用module_exit宏指明的函数,也就是这里的hello_exit函数。有了这三要素,内核模块就算是编写 好了。
        这里打印信息用到了printk函数,注意在内核中打印信息使用printk而不是printf,其中KERN_WARNING是内核打印的优先级,内核打印函数共有8个优先级,具体如下:

   

  图片来自网络。

  关于printk函数

  

  2、内核模块的编译
    内核模块的编译通过编写makefile来完成,其格式比较固定。

obj-m :=hello.o

KDIR := /home/bumblebee/exercise/arm4/lesson3/linux-mini2440

all:
    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm

clean:
    rm -f *.o *.ko *.order *.symvers

    (1)、当内核模块只需要一个c文件生成时采用如图第一行所示的编写方式,若由多个c文件生成则采用以下方式。
helloworld-objs    :=file1.o    file2.o    file3.o
    (2)、KDIR用来保存内核代码的路径,由于内核模块的编译是依赖于内核的信息的,所以需要将内核代码的路径用这个变量保存。
    (3)、-C指明要进入-C后面的路径(内核路径)编译模块,M指明了模块文件的路径。
    (4)、最后编写clean伪指令,清除产生的中间文件和.ko文件。
    (5)、rmmod的时候要在/lib/modules目录下面有和内核模块的内核版本一致的目录名经常用(uname  -r)来获取内核版本。
            命令:mkdir  -p  /lib/modules/$(uname  -r)。