Linux那些事儿之我是U盘(3)变态的模块机制 – fudan

请看下面这段代码,她就是Linux下的一个最简单的模块.当你安装这个模块的时候,她会用她特有的语言向你表白,"Hello,world!",千真万确,她没有说"Honey,I love you!",虽然,她可以这么说,如果你要求她这么说.而后来你卸载了这个模块,你无情抛弃了她,她很伤心,她很绝望,但她没有抱怨,她只是淡淡地说,"Goodbye,cruel world!"(再见,残酷的世界!)

++++++++++++++++++hello.c++++++++++++++++++++

1 #include <linux/init.h> /* Needed for the macros */ 2 #include <linux/module.h> /* Needed for all modules */ 3 MODULE_LICENSE("Dual BSD/GPL"); 4 MODULE_AUTHOR("fudan_abc"); 5 6 static int __init hello_init(void) 7 { 8 printk(KERN_ALERT "Hello, world!/n"); 9 return 0; 10 } 11 12 static void __exit hello_exit(void) 13 { 14 printk(KERN_ALERT "Goodbye, cruel world/n"); 15 } 16 17 module_init(hello_init); 18 module_exit(hello_exit);

++++++++++++++++++++++++++++++++++++++++++++++++

你需要使用module_init()和module_exit(),你可以称她们为函数,不过实际上她们是一些宏(macro),现在你可以不用去知道她们背后的故事,只需要知道,在Linux Kernel 2.6的世界里,你写的任何一个模块都需要使用她们来初始化或退出,或者说注册以及后来的注销.当你用module_init()为一个模块注册了之后,在你使用insmod这个命令去安装的时候,module_init()注册的函数将会被执行,而当你用rmmod这个命令去卸载一个模块的时候,module_exit()注册的函数将会被执行.module_init()被称为驱动程序的初始化入口(driver initialization entry point).

怎么样演示以上代码的运行呢?没错,你需要一个Makefile.

+++++++++++++++++++++Makefile+++++++++++++++++++++++++++

1 # To build modules outside of the kernel tree, we run "make" 2 # in the kernel source tree; the Makefile these then includes this 3 # Makefile once again. 4 # This conditional selects whether we are being included from the 5 # kernel Makefile or not. 6 ifeq ($(KERNELRELEASE),) 7 8 # Assume the source tree is where the running kernel was built 9 # You should set KERNELDIR in the environment if it’s elsewhere 10 KERNELDIR ?= /lib/modules/$(shell uname -r)/build 11 # The current directory is passed to sub-makes as argument 12 PWD := $(shell pwd) 13 14 modules: 15 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 16 17 modules_install: 18 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install 19 20 clean: 21 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions 22 23 .PHONY: modules modules_install clean 24 25 else 26 # called from kernel build system: just declare what our modules are 27 obj-m := hello.o 28 endif++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

在lwn上可以找到这个例子,你可以把以上两个文件放在你的某个目录下,然后执行make,也许你不一定能成功,因为LK 2.6要求你编译模块之前,必须先在内核源代码目录下执行make,换言之,你必须先配置过内核,执行过make,然后才能make你自己的模块.原因我就不细说了,你按着她要求的这么去做就行了.在内核顶层目录make过之后,你就可以在你当前放置Makefile的目录下执行make了.Ok,make之后你就应该看到一个叫做hello.ko的文件生成了,恭喜你,这就是你将要测试的模块.

执行命令,

#insmod hello.ko

同时在另一个窗口,用命令tail -f /var/log/messages察看日志文件,你会看到

Hello world被打印了出来.

再执行命令,

#rmmod hello.ko

此时,在另一窗口你会看到Goodbye,cruel world!被打印了出来.

到这里,我该恭喜你,因为你已经能够编写Linux内核模块了.这种感觉很美妙,不是吗?你可以嘲笑秦皇汉武略输文采唐宗宋祖稍逊风骚,还可以嘲笑一代天骄成吉思汗只识弯弓射大雕了.是的,Twins姐姐(s)告诉我们,只要我喜欢,还有什么不可以.

日后我们会看到,2.6内核中,每个模块都是以module_init开始,以module_exit结束.大多数来说没有必要知道这是为什么,记住就可以了,相信每一个对Linux有一点常识的人都会知道这一点的,对大多数人来说,这就像是1+1为什么等于2一样,就像是两点之间最短的是直线,不需要证明,如果一定要证明两点之间直线最短,可以扔一块骨头在B点,让一条狗从A点出发,你会发现狗走的是直线,是的,狗都知道,你还能不知道吗?

我希望你能知道,我的心永远只为你跳动。

Linux那些事儿之我是U盘(3)变态的模块机制 – fudan

相关文章:

你感兴趣的文章:

标签云: