ubuntu下helloworld内核模块编译、加载/卸载
2016-09-14 18:50
453 查看
1、编写helloworld内核模块的源码
如下是helloworld.c源码
/*注释:
(1).这个模块定义了两个函数, 一个在模块加载到内核时被调用( hello_init )以及一个在模块被去除时被调用( hello_exit ).
moudle_init 和 module_exit 是比较特别的内核宏来指出这两个函数的角色;
(2).宏 (MODULE_LICENSE) 是用来告知内核, 该模块带有一个自由的许可证; 没有这样的说明, 模块在加载时内核会抱怨.
(3).printk 函数在 Linux 内核中定义并且对模块可用,它与标准 C 库函数 printf 的行为相似.
内核需要它自己的打印函数, 因为它靠自己运行, 没有
C 库的帮助.
(4).字串 KERN_EMERG 是消息的优先级,可以用 <1>,等对应的数字代替来前缀于
printk 格式串之前.
注意如果用 KERN_ALERT ,之后要缺少一个逗号
(5).要用helloworld.c,后缀不能少。因为下边的Makefile里实际用的是gcc,它对后缀有要求。
*/
2、编写Makefile
如下是Makefile
/*注释:
上面的不是一个传统的 makefile 的样子,是kbuild makefile语法
(1). obj-m :=hello.o表明有一个模块要从目标文件
hello.o 建立. 在从目标文件建立后结果模块命名为 hello.ko
扩展一点: 如果你有一个模块名为 module.ko, 是来自 2 个源文件( 姑且称之为, file1.c
和 file2.c ), 正确的书写应当是:
obj-m := module.o
module-objs := file1.o
file2.o
(2). make -C $(KDIR):这个命令开始是改变它的目录到用 -C
选项提供的目录下( 就是说, 你的内核源码目录 )
它在那里会发现内核的顶层 makefile。
(3). 这个 M= 选项使 makefile 在试图建立模块目标前, 回到你的模块源码目录。
M=$(PWD) 作为参数传给Makefile,内核中的解释是:make
M=dir modules Make all modules in specified dir
目标, 是指在 obj-m 变量中发现的模块列表, 在我们的例子里设成了 hello.o
(4). $(shell
uname -r):是调用shell命令,在我系统上是2.6.18-92.el5,所以KDIR :=/lib/modules/&(shell
uname -r)/build:
/lib/modules/2.6.18-92.el5/build/是内核源码.
(5)内核源码Makefile中350行有关于KERNELRELEASE定义:
#KERNELRELEASE = $(shell cat include/config/kernel.release
2> /dev/null)
下面,全面的解释一下这个makefile的执行流程:
这个 makefile 在一次典型的建立中要被读 2 次.
(i).在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容,如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C
$(KDIR)指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
(ii).当从内核源码目录返回时,KERNELRELEASE已被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。
obj-m := hello.o表示编译连接后将生成param.ko模块。
这种建立模块的机制你可能感觉笨拙模糊. 一旦你习惯了它, 但是, 你很可能会欣赏这种已经编排进内核建立系统的能力.
*/
3. 编译helloworld内核模块
#sudo make
这时,在hello.c 所在文件夹就会有 hello.ko ,这个就是我们需要的内核模块啦
#sudo make clean
清理编译垃圾。hello.ko 也会清理掉,所以之后要再次make生成hello.ko.
3. 加载/卸载helloworld内核模块
#sudo insmod ./hello.ko
可以到日志文件/var/log/kern.log中,看到内核消息输出,“Hello
world!”
#sudo rmmod ./hello.ko
可以到日志文件/var/log/kern.log中,看到内核消息输出,“exit world!”
4. 让printk内核消息同时输出到控制台
(1)在图形界面的终端,终端里没有内核信息输出"hello
world"exit world!和"exit
world!"。
(2)切换到字符界面终端,就会有输出。
(按ALT+CTRL+F1~F6切换到字符界面)(按ALT+CTRL+F7切换到图形界面)
如下是helloworld.c源码
#include <linux/module.h> //所有模块都需要的头文件 #include <linux/init.h> // init&exit相关宏 MODULE_LICENSE("GPL"); MODULE_AUTHOR("feifei"); MODULE_DESCRIPTION("hello world module"); static int __init hello_init(void){ printk(KERN_ERR "hello world"); return 0; } static void __exit hello_exit(void){ printk(KERN_EMERG "hello exit!"); } module_init(hello_init); module_exit(hello_exit);
/*注释:
(1).这个模块定义了两个函数, 一个在模块加载到内核时被调用( hello_init )以及一个在模块被去除时被调用( hello_exit ).
moudle_init 和 module_exit 是比较特别的内核宏来指出这两个函数的角色;
(2).宏 (MODULE_LICENSE) 是用来告知内核, 该模块带有一个自由的许可证; 没有这样的说明, 模块在加载时内核会抱怨.
(3).printk 函数在 Linux 内核中定义并且对模块可用,它与标准 C 库函数 printf 的行为相似.
内核需要它自己的打印函数, 因为它靠自己运行, 没有
C 库的帮助.
(4).字串 KERN_EMERG 是消息的优先级,可以用 <1>,等对应的数字代替来前缀于
printk 格式串之前.
注意如果用 KERN_ALERT ,之后要缺少一个逗号
(5).要用helloworld.c,后缀不能少。因为下边的Makefile里实际用的是gcc,它对后缀有要求。
*/
2、编写Makefile
如下是Makefile
ifeq ($(KERNELRELEASE),) KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) modules: $(MAKE) -C $(KDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KDIR) M=$(PWD) modules_install clean: rm -rf *.o *.ko .depend *.mod.o *.mod.c Module.* modules.* .PHONY:modules modules_install clean else obj-m :=hello.o endif
/*注释:
上面的不是一个传统的 makefile 的样子,是kbuild makefile语法
(1). obj-m :=hello.o表明有一个模块要从目标文件
hello.o 建立. 在从目标文件建立后结果模块命名为 hello.ko
扩展一点: 如果你有一个模块名为 module.ko, 是来自 2 个源文件( 姑且称之为, file1.c
和 file2.c ), 正确的书写应当是:
obj-m := module.o
module-objs := file1.o
file2.o
(2). make -C $(KDIR):这个命令开始是改变它的目录到用 -C
选项提供的目录下( 就是说, 你的内核源码目录 )
它在那里会发现内核的顶层 makefile。
(3). 这个 M= 选项使 makefile 在试图建立模块目标前, 回到你的模块源码目录。
M=$(PWD) 作为参数传给Makefile,内核中的解释是:make
M=dir modules Make all modules in specified dir
目标, 是指在 obj-m 变量中发现的模块列表, 在我们的例子里设成了 hello.o
(4). $(shell
uname -r):是调用shell命令,在我系统上是2.6.18-92.el5,所以KDIR :=/lib/modules/&(shell
uname -r)/build:
/lib/modules/2.6.18-92.el5/build/是内核源码.
(5)内核源码Makefile中350行有关于KERNELRELEASE定义:
#KERNELRELEASE = $(shell cat include/config/kernel.release
2> /dev/null)
下面,全面的解释一下这个makefile的执行流程:
这个 makefile 在一次典型的建立中要被读 2 次.
(i).在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容,如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C
$(KDIR)指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
(ii).当从内核源码目录返回时,KERNELRELEASE已被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名。
obj-m := hello.o表示编译连接后将生成param.ko模块。
这种建立模块的机制你可能感觉笨拙模糊. 一旦你习惯了它, 但是, 你很可能会欣赏这种已经编排进内核建立系统的能力.
*/
3. 编译helloworld内核模块
#sudo make
这时,在hello.c 所在文件夹就会有 hello.ko ,这个就是我们需要的内核模块啦
#sudo make clean
清理编译垃圾。hello.ko 也会清理掉,所以之后要再次make生成hello.ko.
3. 加载/卸载helloworld内核模块
#sudo insmod ./hello.ko
可以到日志文件/var/log/kern.log中,看到内核消息输出,“Hello
world!”
#sudo rmmod ./hello.ko
可以到日志文件/var/log/kern.log中,看到内核消息输出,“exit world!”
4. 让printk内核消息同时输出到控制台
(1)在图形界面的终端,终端里没有内核信息输出"hello
world"exit world!和"exit
world!"。
(2)切换到字符界面终端,就会有输出。
(按ALT+CTRL+F1~F6切换到字符界面)(按ALT+CTRL+F7切换到图形界面)
相关文章推荐
- 最简单的helloworld模块编译加载(linux3.5内核源码树建立)
- 内核模块编写,编译,加载和卸载过程
- ubuntu下编译内核模块ko,并加载
- 【TINY4412】LINUX学习笔记:(2)内核模块编译、安装、加载、卸载
- 内核模块编译、加载&卸载及查看运行结果 -- linux内核
- 内核模块的编写、编译、加载、卸载;Makefile的编写
- ubuntu下helloworld内核模块编译
- 编译,加载并卸载一个内核模块
- ubuntu内核模块加载不能看的printk输出的问题
- linux启动时对编译进内核驱动模块的加载
- 内核编译加载layer7补丁和模块
- Code maturity level options 代码成熟度选项 [*]Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完成的代码与驱动.除非你是测试人员或者开发者,否则请勿选择 我是开发者,所以选[*] Loadable module support 可加载模块支持 [*]Enable loadable module support 内核编译配置选项简介 (2.4.20-8
- 在Linux 2.6内核下编译可以加载的内核模块
- Linuxx 2.6内核可加载模块的编译
- Linux 2.6 内核驱动模块的编译和加载
- 内核编译加载layer7补丁和模块-043
- Linux 2.6内核的编译步骤及模块的动态加载
- Ubuntu下编译的第一个内核模块
- 在Linux 2.6内核下编译可以加载的内核模块_转载
- Linux 2.6内核的编译步骤及模块的动态加载