最近, 感觉自己应该学一下linux的东西了, 于是,拿linux内核来开刀, 其实, 自己都不知道会坚持多久, 但是, 但是!!!既然现在开始了, 遇到一些问题, 就应该把它记录下, 以方便自己温习和别人参考。
我使用的是ubuntu 10.04 Server版的linux, 在这里, 我假设你已经编译了内核(什么?你还没有编译内核,呃, 那么你还是不要往下看了, 先去把内核编译了吧, 具体的编译过程, 可以参考:http://blog.csdn.net/xiao229404041/article/details/7007944)。 那么, 就开始我们的第一个内核模块编写旅程吧。
step 1:
编写一个最简单的内核模块, 可以抄书或者自己写, 谁的第一个hello world不是临摹而来的呢。
新建一个hello_world.c文件, vim hello_module.c, 然后输入以下内容:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static char *hello_words = "welcome to linux kernel world!";
static int words_count = 29;
static int hello_word_init(void)
{
printk(KERN_INFO " words content:%s\n", hello_words);
printk(KERN_INFO " words num:%d\n", words_count);
return 0;
}
static void hello_word_exit()
{
printk(KERN_ALERT " hello word exit\n");
}
module_init(hello_word_init);
module_exit(hello_word_exit);
module_param(words_count, int, S_IRUGO);
module_param(hello_words, charp, S_IRUGO);
MODULE_AUTHOR("eafly huang");
MODULE_DESCRIPTION("A hello word module for testing module parameters");
MODULE_VERSION("V1.0");
嗯, 这里面你以为hello_word写错了, 其实是我故意的, 不用管它, 照写就是。
step2:
编译, 使用gcc hello_module.c, 回车后, 悲剧了, 出现:
hello_module.c:1:24: error: linux/init.h: No such file or directory
hello_module.c:2:26: error: linux/module.h: No such file or directory
出师未捷身先死, 这不是打击我学习linux 内核的积极性吗? 还好有百度(不用鄙视我, 这几天Google又用不了了。), 搜索后发现linux内核模块编译不能使用常用的方法编译(见链接:http://bbs.csdn.net/topics/340193347), 要写一个Makefile(也就是在你放hello_module.c的目录下cat 一个Makefile, 名字不要写错了)来编译, 但是, 但是我不懂Makefile怎么办?难道中断去学习Makefile? 还是有百度, 搜索一下, Makefile的写法就出来了, 写个最简单的, 不要那么高大上:
ifneq ($(KERNELRELEASE),)
mymodule-objs := hello_module.o
obj-m := hello_module.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
兄弟, 注意命令前加Tab哦, 要不然用不了不要埋怨我。
以上的Makefile不是那么的优美, 胜在能用(我会告诉你我是半copy来的吗?)
okey, Makefile有了, 那么总该可以编译了吧。
Step3:
在终端输入: make
哗啦啦出来:
root@ubuntu:/home/eafly/work/source/hello_module# make
make -C /lib/modules/2.6.35.9/build M=/home/eafly/work/source/hello_module
make[1]: Entering directory `/home/eafly/work/kernel/linux-2.6.35.9'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory `/home/eafly/work/kernel/linux-2.6.35.9'
root@ubuntu:/home/eafly/work/source/hello_module#
太感人了, 终于出来了有木有, 有木有!!!
S:tep4:
既然出来了, 那么就该运行一下看看效果了:
终端输入:insmod hello_module.ko
如果提示你没有权限, 请切换到root
然后你以为会出来什么?什么都没有, 当然没有, 都说是内核模块, 肯定是在某个不为人知的地方了(其实也就是log里面了。)
Step5:
继续在终端输入: tail -n 2 /var/log/messages
总算出来了:
root@ubuntu:/home/eafly/work/source/hello_module# tail -n 2 /var/log/messages
Jun 10 07:52:24 ubuntu kernel: [ 3953.986520] words content:welcome to linux kernel world!
Jun 10 07:52:24 ubuntu kernel: [ 3953.986526] words num:29
这里如果你用了别的非版本ubuntu系统或者别的linux系统, 可能就不是这个目录下的 文件了, 比如我的阿里云用了16.04版本, 就得到 /var/log/kern.log中取找。 不管如何, 到 /var/log/下去找, 应该能找到的。
卸载模块就比较简单了, 先查看一下我们加载了的模块: lsmod
是不是看到了先前insmod进去的hello_module, 然后我们使用命令rmmod hello_module, 再到 /var/log/下去看看, 就可以看到卸载时打印的信息了。