记第一次写Linux Driver

2.6之后,驱动可以以模块的方式加载到内核中执行。我们在自己的机器上写driver要配合对应的内核树,
以便和源代码树中的目标文件相连。怎么建立这个内核源码树呢?可以从官网下载相对应的内核源码,编译之。

首先,看看我的内核版本。

[linc@localhost ~]$ uname -r
2.6.35.6-45.fc14.i686

那么去官网www.kernel.org下载2.6.35.6的源码吧。
在首页找不到你要的版本不要急,点击FTP的链接,找到你想要的版本吧。
创建个目录,将源码解压在其中。(tar xfvz yourfile)
编译的第一项是内核配置,我的系统的Fedora,出现了点问题:
在源码目录下root执行make menuconfig,
  出现错误:

  *** Unable to find the ncurses libraries or the
  *** required header files.
  *** 'make menuconfig' requires the ncurses libraries.
  ***
  *** Install ncurses (ncurses-devel) and try again.
  ***
  make[1]: *** [scripts/kconfig/dochecklxdialog] 错误 1
  make: *** [menuconfig] 错误 

解决办法:
这是由于ncurses图形库导致的,下载它就好了。
  yum install ncurses
  yum install ncurses-devel
这次继续执行,出现配置界面。按如下来操作:
Loadable module support ---->
选择Module versioning support(按Y就ok),这个功能可以让你使用其他版本的内核模块。


接下来就可以编译了:
还是此目录下,执行make。很长时间,根据机器配置而异。喝茶去吧。
接着编译压缩形式的内核,make bzImage

[root@localhost linux-2.6.35.6]# make bzImage
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CHK     include/linux/version.h
make[2]: `scripts/unifdef' is up to date.
  TEST    posttest
Succeed: decoded and checked 1249053 instructions
Kernel: arch/x86/boot/bzImage is ready  (#2)
继续编译模块并将它们安装到系统标准位置:
make modules
make modules_install
完成后,/lib/modules/下多了个2.6.35.6目录。


至此,我们的内核树算是建立完成。
下面写个hello world来检验一下吧。

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)
{
        printk(KERN_ALERT "Hello,world.i am linc.\n");
        return 0;
}

static void hello_exit(void)
{
        printk(KERN_ALERT "Goodbye, i am linc.\n");

}

module_init(hello_init);
module_exit(hello_exit);
写个makefile来编译它:
#如果已经定义KERNELRELEASE,说明是从内核构造系统调用的,
#可利用其内建语句
ifneq ($(KERNELRELEASE),)
obj-m := test.o
#否则是从命令行调用的,需要使用内核构造系统
else
        KDIR := /lib/modules/2.6.35.6/build
all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif

编译:
[root@localhost drivers]# make
make -C /lib/modules/2.6.35.6/build M=/home/linc/linux/workspace/drivers modules
make[1]: Entering directory `/usr/src/kernels/linux-2.6.35.6'
  CC [M]  /home/linc/linux/workspace/drivers/test.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/linc/linux/workspace/drivers/test.mod.o
  LD [M]  /home/linc/linux/workspace/drivers/test.ko
make[1]: Leaving directory `/usr/src/kernels/linux-2.6.35.6'


安装和卸载:

insmod test.ko

rmmod test.ko

如果此时仍然遇到问题:

[root@localhost drivers]# insmod test.ko 
insmod: error inserting 'test.ko': -1 Invalid module format
我们看一下具体详细信息:

[root@localhost drivers]# dmesg | tail

[  356.269653] test: version magic '2.6.35.6 SMP mod_unload modversions 686 ' should be '2.6.35.6-45.fc14.i686 SMP mod_unload 686 '
说明ko的kernel版本与当前运行的版本仍然不一致。此时我尝试重新编译内核,结果仍然一样。就参考

Linux 2.6.x 内核模块加载错误 “Invalid module format” 解决办法》 将版本强制修改一下,让其保持一致。方法如下:

找到utsrelease.h文件,在源码树下linux-2.6.35.6/include/generated。将版本号修改。重新编译,发现仍有错误:

[ 1149.371180] test: version magic '2.6.35.6-45.fc14.i686 SMP mod_unload modversions 686 ' should be '2.6.35.6-45.fc14.i686 SMP mod_unload 686 '
对比上述信息,发现我的VERMAGIC_STRING多了一个词“modversions”,好吧,为了一直,索性将linux-2.6.35.6/include/linux/vermagic.h文件中对VERMAGIC_STRING做

下调整。去掉MODULE_VERMAGIC_MODVERSIONS信息。如下:

#include <generated/utsrelease.h>
#include <linux/module.h>

/* Simply sanity version stamp for modules. */
#ifdef CONFIG_SMP
#define MODULE_VERMAGIC_SMP "SMP "
#else
#define MODULE_VERMAGIC_SMP ""
#endif
#ifdef CONFIG_PREEMPT
#define MODULE_VERMAGIC_PREEMPT "preempt "
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
#ifdef CONFIG_MODULE_UNLOAD
#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
#else
#define MODULE_VERMAGIC_MODULE_UNLOAD ""
#endif
#ifdef CONFIG_MODVERSIONS
#define MODULE_VERMAGIC_MODVERSIONS "modversions "
#else
#define MODULE_VERMAGIC_MODVERSIONS ""
#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif

#define VERMAGIC_STRING                                                 \
        UTS_RELEASE " "                                                 \
        MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT                     \
        MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC

至此,重新编译模块。一切正常。

[root@localhost drivers]# insmod test.ko
[root@localhost drivers]# rmmod test.ko
[root@localhost drivers]# dmesg | tail
[ 1586.792291] Hello,world.i am linc.
[ 1696.536632] Goodbye, i am linc.


参考:
http://blog.csdn.net/xuxinyl/article/details/6996433
http://www.cnblogs.com/Jezze/archive/2011/12/23/2299871.html

《Linux设备驱动程序》第二章



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值