您的位置:首页 > 其它

内核模块学习--编译自己的第一个内核模块hello_module

2012-03-29 20:38 691 查看
1,下载源码

xin@xin-desktop:~$ sudo apt-get source linux-image-2.6.32-38-generic

最终安装在目录:/usr/src/linux-2.6.32/

2,编写源码hello_module.c和Makefile

(1)新建一个目录mytest

xin@xin-desktop:~/mytest$ vi hello_module.c

#include <linux/init.h>         /* printk() */
#include <linux/module.h>       /* __init __exit */

static int  __init  hello_init(void)      /*模块加载函数,通过insmod命令加载模块时,被自动执行*/
{
printk(KERN_INFO " Hello World enter\n");
return 0;
}
static void  __exit  hello_exit(void)    /*模块卸载函数,当通过rmmod命令卸载时,会被自动执行*/
{
printk(KERN_INFO " Hello World exit\n ");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("xin");           /*模块作者,可选*/
MODULE_LICENSE("Dual BSD/GPL");     /*模块许可证明,描述内核模块的许可权限,必须*/
MODULE_DESCRIPTION("A simple Hello World Module"); /*模块说明,可选*/


(2)写一个Makefile文件:

内容如下:

#目标文件
obj-m :=hello_module.o

#当模块有多个文件组成时,添加本句
#module-objs := file1.o file.o

#内核路径,根据实际情况换成自己的内核路径,嵌入式的换成嵌入式,PC机的指定PC机路>径
KDIR :=/usr/src/linux-2.6.32/

#模块源文件路径
PWD := $(shell pwd)

all:
$(MAKE)  -C  $(KDIR)  SUBDIRS=$(PWD)  modules
@rm -rf *.mod.*
@rm -rf .*.cmd
@rm -rf *.o
@rm -rf Module.*
clean:
rm -rf *.ko


3,编译

xin@xin-desktop:~/mytest$ make

make: Entering directory `/usr/src/linux-2.6.32'

ERROR: Kernel configuration is invalid.

include/linux/autoconf.h or include/config/auto.conf are missing.

Run 'make oldconfig && make prepare' on kernel src to fix it.

WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers

is missing; modules will have no dependencies and modversions.

........................................

........................................

解决方法:

xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make oldconfig

xin@xin-desktop:/usr/src/linux-2.6.32$ sudo make prepare

再次编译:

xin@xin-desktop:~/mytest$ make

还是有错:

make: Entering directory `/usr/src/linux-2.6.32'

WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers

is missing; modules will have no dependencies and modversions.

CC [M] /home/xin/mytest/hello_module.o

Building modules, stage 2.

MODPOST 1 modules

/bin/sh: scripts/mod/modpost: not found

make[1]: *** [__modpost] 错误 127

make: *** [modules] 错误 2

make: Leaving directory `/usr/src/linux-2.6.32'

看到提示说没有scripts/mod/modpost,那我们就编译它

xin@xin-desktop:/usr/src/linux-2.6.32$ make scripts

HOSTCC scripts/genksyms/genksyms.o

SHIPPED scripts/genksyms/lex.c

SHIPPED scripts/genksyms/parse.h

SHIPPED scripts/genksyms/keywords.c

HOSTCC scripts/genksyms/lex.o

SHIPPED scripts/genksyms/parse.c

HOSTCC scripts/genksyms/parse.o

HOSTLD scripts/genksyms/genksyms

CC scripts/mod/empty.o

HOSTCC scripts/mod/mk_elfconfig

MKELF scripts/mod/elfconfig.h

HOSTCC scripts/mod/file2alias.o

HOSTCC scripts/mod/modpost.o

HOSTCC scripts/mod/sumversion.o

HOSTLD scripts/mod/modpost

HOSTCC scripts/kallsyms

HOSTCC scripts/conmakehash

OK,好了

再来解决这一个warning(前面没有关注,后面发现这个还是致命的):

WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers

is missing; modules will have no dependencies and modversions.

原因:通常头核心包中是没有Module.symvers这个文件的,要想获取这个文件只能到下载相同版本核心的头文件,是下载不是

apt-get install !!!,只有下载的头文件中才有这个Module.symvers。把Module.symvers 复制到核心包中。

然后重新编译驱动:xin@xin-desktop:~/mytest$ make

将解决这个warning,同时也解决了版本不正确的问题。

(我不知道有多少人会碰上这样的问题,反正google中我发现没有人能说明白这个问题)

4,加载模块

xin@xin-desktop:~/mytest$ ls

hello_module.c modules.order hello_module.ko Makefile

xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko

xin@xin-desktop:~/mytest$ lsmod | grep hello_module

hello_module 593 0

ps:

不解决上面的warning,是可以编译成功的。但是在执行加载后

xin@xin-desktop:~/mytest$ sudo insmod hello_module.ko

报错:insmod: error inserting 'hellomod.ko': -1 Invalid module format

查了很多资料,普遍的观点是:

内核无法加载模块的原因是因为记载版本号的字符串(正规说法:版本印戳)和当前正在运行的内核模块的不一样,叫vermagic

此时,可用sudo tail /var/log/messages

你在最后一行应该看到类似下面的提示:

Dec 19 13:42:29 localhost kernel: hellomod: version magic '2.6.24.2 SMP mod_unload 686 4KSTACKS ' should be '2.6.27.7-134.fc10.i686 SMP mod_unload 686 4KSTACKS '

而我的只显示:

Mar 29 16:57:34 xin-desktop kernel: [ 6964.464931] hello_module: no symbol version for module_layout

但是通过modinfo和 uname -r的比较确实不一样

我按照提供的办法,修改源目录下的Makefie

把Makefile第1-4行的值改为当前内核一样的值

VERSION = 2

PATCHLEVEL = 6

SUBLEVEL = 32

EXTRAVERSION = .54+drm33.21

NAME = Man-Eating Seals of Antiquity

确定你当前内核的值,通过

vi /lib/modules/`uname -r`/build/Makefile

但是,我这样改过之后,还是又上面加载不上的问题,而且版本号跟写进Makefile的不是一样的,编译完成的是这样的:

2.6.32.57+drm33.23 SMP mod_unload modversions 586。

即便我把/usr/src/linux-2.6.32内核源码中的Makefile改了,也是这样的,我一直没有搞清楚,到底内核版本号是在哪里设置的。

最后,消除了这个warning后,虽然内核版本号仍不一样,但是可以加载了。

当前已经加载的内核模块video的信息:

xin@xin-desktop:~/mytest$ modinfo video

filename: /lib/modules/2.6.32-38-generic/kernel/drivers/acpi/video.ko

license: GPL

description: ACPI Video Driver

author: Bruno Ducrot

srcversion: A52E70043443277D9757C8E

alias: acpi*:LNXVIDEO:*

depends: output

vermagic: 2.6.32-38-generic SMP mod_unload modversions 586

parm: brightness_switch_enabled:bool

hello_module的信息:

xin@xin-desktop:~/mytest$ modinfo hello_module.ko

filename: hello_module.ko

alias: a simplest module

description: A simple Hello World Module

license: Dual BSD/GPL

author: xin

srcversion: B757E1EEAD29F16BF0B6737

depends:

vermagic: 2.6.32.57+drm33.23 SMP mod_unload modversions 586

注意到 两者的vermagic是不一样的,但是可以加载hello_module.ko模块
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: