linux 模块编程

上一篇 / 下一篇  2012-05-18 10:15:53 / 个人分类:linux 驱动测试

linux模块编程

一、摘要

   Linux内核模块编程的资料有些纷繁复杂,有的过于简单,有的过于庞杂,我试图用笔记的形式想读者展示怎样来进程Linux模块编程,力图做到简明扼要,这篇文章也是作为本人备忘的资料,所以有些地方过于简略是难免的。本来这篇文章的目的就是让用户知其然,至于所以然还是请参考相应的资料,其实最好的资料莫过于Linux Kernel Source

二、Linux模块简介

        首先这个module不同于microkernelmodulemicrokernelmodule是一个个的daemon进程,工作于用户空间,Linuxmodule只是一个内核的目标代码,内核通过执行运行时的连接,来把它整合到kernel中去,所以说Linuxmodule机制并没有改变Linux内核为monolithic OS本质,其module也是工作于内核模式,享有内核的所有特权。

 

至于为什么要引入Linux Kernle Module(一下简称LKM),我想至少有一下几点:

 

l 模块化编程的需要,降低开发和维护成本。

l 增强系统的灵活性,使得修改一些内核功能而不必重新编译内核和重启系统。

l 降低内核编程的复杂性,使入门门槛降低。

三、案例

3.1、源码HelloModule

        现在我们介绍一个运行内核态的HelloWorld程序,它其实是一个最简单的驱动程序模块。

   我们将Hello Module的源代码放在/root/code目录

文件名字为hellomodule.c,源代码内容如下

#include <linux/kernel.h>

#include <linux/module.h>

 

static int _init sep0611_hello_module_init(void)

{

      printk("Hello,sep0611 module is installed! \n");

      return 0;

}

 

static void _exit sep0611_hello_module_cleanup(void)

{

      printk("Good-bye,sep0611 module was removed!\n");

}

MODULE_LICENSE("GPL");

MODULE_AUTHOR(DRIVER_AUTHOR);  /* Who wrote this module? */

MODULE_DESCRIPTION(DRIVER_DESC);     /* What does this module do */

 

module_init(sep0611_hello_module_init);

module_exit(sep0611_hello_module_cleanup);

3.2编译Hello Module源代码

   由于这个模块是加到嵌入式Linux的内核中,所以它肯定会用到许多嵌入式Linux源码的头文件,我们的嵌入式linux的内核源码位置在/linux/下面,这中间的链接过程非常复杂,为了不让我们手动输入编译指令,一般编译2.6版本的驱动模块需要把驱动代码加入内核代码树,并做相应的配置,如下步骤

Step1:编辑文件Kconfig,加入驱动选项,使之在make menuconfig的时候出现,打开/Linux/DDR2-Demo/kernel/drivers/char/Kconfig文件,添加如图1-1所示:

zhangjie@WX-ASIC-S02-Android:~/Linux/DDR2-Demo/kernel/drivers/char$ vi Kconfig

1-1 Kconfig修改

这是我们添加的部分。

保存退出,这时在kernel目录位置运行一下make menuconfig就可以在Device Drivers/Character devices菜单中看到刚才添加的选项了,按下空格键将会选择为<M>,此意为要把该选项编译为模块方式;再按下空格键会变为<*>,意为要把该选项编译到内核中,再次我们选择<M>,如图1-21-31-4

zhangjie@WX-ASIC-S02-Android:~/Linux/DDR2-Demo/kernel$ make menuconfig

1-2 Device Drivers选项

1-3 Character devices选项

 

1-4 sep0611 hello module

Step2:通过上一步,我们虽然可以在配置内核的时候进行选择,但实际中此时执行编译内核还是不能把hellomodule.c编译进去,还需要在makefile中把内核配置选项和真正的源码联系起来,打开kernel/drivers/char/Makefile,如图1-5添加并保存退出:

zhangjie@WX-ASIC-S02-Android:~/Linux/DDR2-Demo/kernel/drivers/char$ vi Makefile

1-5 Makefile修改

此处为我们添加的:其中CONFIG_SEP0611_hellomodule为在Kconfig使用“_”连接,同时config变为大写CONFIG,后面的hellomodule.o为对应hellomodule.c的要生成的。

Step3:这时回到kernel目录位置,执行make modules,就可以生成我们需要的内容模块文件hellomodule.ko了,如图1-6

zhangjie@WX-ASIC-S02-Android:~/Linux/DDR2-Demo/kernel$ make modules

1-6编译的模块

上面的make modules是编译所有的ko文件,当你只需要编译自己的ko,而不需要编译其他的时候,我们可以使用:

make CONFIG_SEP0611_hellomodule=m -C

/home/zhangjie/Linux/DDR2-Demo/kernel M=/home/zhangjie/Linux/DDR2-Demo/kernel/drivers/char modules

CONFIG_SEP0611_hellomodule=m是你想要编译的模块

-C:后面的是kernel目录,即你编译的Makefile的目录

M=后面的路径为你编译生成的*.ko所在的路径

注:编译模块的时候首先要先编译uImage,当你make clean后,也要重新编译uImage

3.3、把HelloModule下载到开发板并安装使用

      最简单的方法莫过于把hellomodule.ko拷贝到网络文件系统中,这样你就可以直接在板子上运行程序了。假设我们已经把hellomodule.ko放到了板子的/目录下,现在执行:

#insmod hellomodule.ko

可以看到该模块已经被装载了;在执行,可以看到该模块被卸载

#rmmod hellomodule.ko

整个过程如图1-7

1-7模块加载和删除


TAG: Linux linux module

 

评分:0

我来说两句

Open Toolbar