曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 12795|回复: 3
打印 上一主题 下一主题

"hello world" 简单内核模块

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-8-7 01:27:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init (void)
{
    printk("hello linux kernel\n");
   
    return 0;
}

static void hello_exit (void)
{
    printk("bye..lwave from the kernel\n");
   
}

module_init(hello_init);
module_exit(hello_exit);
编译方法( 只针对 2.6 内核 )
编写 Makefile 文件,Makefile 文件内容很简单,只有一行:
obj-m := hello.o
执行命令
beyes@linux-beyes:~/C/kernel> make -C /usr/src/linux-2.6.30 M=`pwd` modules
make: Entering directory `/usr/src/linux-2.6.30'
  CC [M]  /home/beyes/C/kernel/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/beyes/C/kernel/hello.mod.o
  LD [M]  /home/beyes/C/kernel/hello.ko
make: Leaving directory `/usr/src/linux-2.6.30'
beyes@linux-beyes:~/C/kernel> ls
hello.c  hello.ko  hello.mod.c  hello.mod.o  hello.o  Makefile  Module.markers  modules.order  Module.symvers

说明
经过以上简单几步后,即生成了一个简单的模块。这个模块在加载之后,属于内核空间,是内核空间的一部分,而不是用户空间。
在 2.6 内核版本里,编译模块,首先需要有一份完整的,编译了的内核源代码树。编译内核见:http://www.groad.net/bbs/read.php?tid=770

在 Makefile 文件里,obj-m 名字不能改变成别的,假如写成 objj-m ,那么编译后并不会输出 hello.ko 内核模块文件,而是只有:
make: Entering directory `/usr/src/linux-2.6.30'
  Building modules, stage 2.
  MODPOST 0 modules
make: Leaving directory `/usr/src/linux-2.6.30'
beyes@linux-beyes:~/C/kernel> ls
hello.c  Makefile  Module.markers  modules.order  Module.symvers

假如要从两个源文件里编译得到一个名为 module.ko 的模块,那么 Makefile 文件可写成:
obj-m := module.o
module-objs := file1.o file2.o

在编译命令 make -C /usr/src/linux-2.6.30 M=`pwd` modules 中,
-C 参数后面接内核源码树路径,这是个顶层路径,也就是说在这目录下可以找到编译内核的 Makefile 文件;
M= 选项使 "makefile" 移动回到所要编译的源码所在的目录下。也就是说,一开始,需要找到内核源码树下的 Makefile,然后需要再找到欲编译源码下的 Makefile .

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
沙发
 楼主| 发表于 2009-8-7 02:06:07 | 只看该作者

在用户空间加载和卸载驱动

通过以下命令加载上面编译生成的模块
linux-beyes:/home/beyes/C/kernel # insmod ./hello.ko

注意的是,如果使用在图形系统下的虚拟终端,那不会看到输出信息,但是这些信息一般被保存在 /var/log/messages 文件里:
linux-beyes:/home/beyes/C/kernel # cat /var/log/messages | grep hello
Aug  7 01:55:35 linux-beyes kernel: hello linux kernel


卸载模块使用 rmmod 命令
rmmod hello

卸载模块时,如果是是在图形系统下的虚拟终端,那么退出信息同样保存在 /var/log/messages 文件里:
linux-beyes:/home/beyes/C/kernel # cat /var/log/messages | grep bye
Aug  7 02:02:56 linux-beyes kernel: bye..lwave from the kernel

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
板凳
 楼主| 发表于 2009-8-10 14:41:11 | 只看该作者

使用当前运行的内核

Makefile 文件内容如下:
[Plain Text] 纯文本查看 复制代码
obj-m := hello.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD  := $(shell pwd)

default:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
    rm -rf *.ko
    rm -rf *.mod.*
    rm -rf .*.cmd
    rm -rf *.o

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
地板
 楼主| 发表于 2010-7-25 17:14:53 | 只看该作者

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

如果编译时出现:
  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.
可以尝试:
make oldconfig
make prepare
make oldconfig    : 基于已有的.config进行配置, 若有新的符号, 它将询问用户.

这时候再编译,可能会出现:
/bin/sh: scripts/mod/modpost: 没有那个文件或目录
make[1]: *** [__modpost] 错误 127
make: *** [modules] 错误 2
再使用下面命令:
make scripts
最后编译成功。

如果出现
 insmod:error inserting 'hello.ko': -1 Invalid module format
错误,则查看日志文件tail /var/log/messages 文件,若是提示 "no symbol version for module_layout" 错误,则使用以下语句编译:
make -C /lib/modules/`uname -r`/build M=`pwd` modules
而不是直接在 -C 参数后填上 /usr/src/linux-.2.6.xxx 这样的路径直接指向内核源码树,因为按照错误提示,应该是找不到 modules.symbols 文件所致。

关于 /lib/modules 目录的说明:

该目录包含了内核模块及其他文件. 注意, modules中一般会有多个目录: 系统自带的内核模块在这里, 你编译自己的内核模块后, 它们也会被安装到这里. 不同的目录由内核版本号来区分. 即modules里目录的名称是内核版本号. (使用$ uname -r 可知当前系统内核所用的模块位于哪个目录).

/lib/modules/<kernel-version>/build
储存为该版本的内核编译新模块所需的文件. 包括Makefile, .config, module.symVers(模块符号信息), 内核头文件(位于include/, include/asm/中)

/lib/modules/<kernel-version>/kernel
储存内核目标文件(以.ko为后缀). 它的目录组织和内核源代码中kernel的目录组织相同.

/lib/modules/<kernel-version>/中:
modules.alias       : 模块别名定义. 模块加载工具使用它来加载相应的模块.
modules.dep        : 定义了模块间的依赖关系.
modules.symbols : 指定符号属于哪个模块.

这些文件都是文本文件, 可以查看它们.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 02:06 , Processed in 0.079447 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表