以LDD3上的hello.c为例:
//hello.c #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT"Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); |
Makefile文件的内容为:
obj-m := hello.o KERNELDIR := /lib/modules/2.6.20/build PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions |
其中,hello.c和Makefile文件应该位于同一个目录下,可以放在/home下,我的两个文件都位于/home/david/.
第四步:编译和装载模块
在文件所处的目录下,执行:
debian:/home/david # make
然后查看该目录下有哪些文件生成:
debian:/home/david # ls -l 总计 28 drwxr-xr-x 2 david david 4096 2007-02-07 17:49 Desktop -rw-r--r-- 1 david david 462 2007-07-20 13:42 hello.c -rw-r--r-- 1 root root 2432 2007-07-20 13:55 hello.ko -rw-r--r-- 1 root root 607 2007-07-20 13:55 hello.mod.c -rw-r--r-- 1 root root 1968 2007-07-20 13:55 hello.mod.o -rw-r--r-- 1 root root 1140 2007-07-20 13:55 hello.o -rw-r--r-- 1 david david 267 2007-07-20 13:48 Makefile -rw-r--r-- 1 root root 0 2007-07-05 14:11 Module.symvers |
回顾文章:Linux常用基本命令及应用技巧
新手刚刚接触linux的时候可能处处感到不便,不过没有关系,接触新的事物都有这样的一个过程,在你用过Linux一段时间后,你就会逐渐了解Linux其实和Windows一样容易掌握。由于操作和使用环境的陌生,如果要完全熟悉Linux的应用我们首先要解决的问题就是对Linux常用命令的熟练掌握。
可见,已经生成模块文件hello.ko.
然后,就可以加载该模块:
debian:/home/david # insmod hello.ko
查看模块是否加载进内核:
debian:/home/david # lsmod
Module Size Used by
hello 1344 0
nfs 219468 0
nfsd 202224 17
…… ……
其中Module名为hello的即为我们所加载的模块.
卸载模块:
debian:/home/david # rmmod hello
同样可以通过lsmod来查看该模块是否被卸载.
这里有两个问题,其一就是printk()输出的问题.LDD3上也说,在加载和卸载模块的时候都会有信息输出在屏幕上,如果在Windows下通过终端仿真器(我们常用的虚拟机算是一种),则在屏幕上看不到任何输出.我同时在虚拟机和和物理机都运行了该模块,均未看到有"Hello, world"(加载模块时printk的输出)或"Goodby, cruel world"(卸载模块时printk的输出). 这个不知道是我操作系统发行版的原因还是系统配置的问题,请了解这个问题的朋友指点一下.
其二,书上讲到如果屏幕上看不到信息,可能输出在某个日志文件里面了,并说可能在/var/log/messages文件中.并且看到网上很多网友也说是输出到这个文件里面.我不知道有没有发现输出在其他日志文件里的,不过我的这个信息输出在/var/log/syslog里面.在加载和卸载完该模块后, 执行命令:
debian:/home/david # cat /var/log/syslog | grep world
可以看到有两行内容.当然,也可以不用grep world, 应该会出现在最后两行.
Jul 20 14:15:29 localhost kernel: Hello, world
Jul 20 14:15:34 localhost kernel: Goodbye, cruel world
这就是printk应该输出的信息.
这里有另外一个方法,可以实现printk的信息输出在屏幕上,即更改printk输出的优先级.例子中的优先级为:KERN_ALERT,优先级为<1>,如果将优先级改为KERN_EMERG即<0>,则可以看到屏幕的输出信息.
修改的方法只是修改一下hello.c中两句printk()的内容,修改后的hello.c如下:
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_EMERG "Hello, world\n"); /*改动部分*/ return 0; } static void hello_exit(void) { printk(KERN_EMERG"Goodbye, cruel world\n"); /*改动部分*/ } module_init(hello_init); module_exit(hello_exit); |
debian:/home/david# insmod hello.ko debian:/home/david# Message from syslogd@localhost at Fri Jul 20 14:27:32 2007 ... localhost kernel: Hello, world debian:/home/david# rmmod hello debian:/home/david# Message from syslogd@localhost at Fri Jul 20 14:27:42 2007 ... localhost kernel: Goodbye, cruel world debian:/home/david |
以上就是整个2.6内核编译步骤以及模块动态加载的方法.理解和解释有误的地方,也请各位浏览本文的朋友指点,也希望能和对内核和驱动感兴趣的朋友交流。
回顾文章:Linux常用基本命令及应用技巧
新手刚刚接触linux的时候可能处处感到不便,不过没有关系,接触新的事物都有这样的一个过程,在你用过Linux一段时间后,你就会逐渐了解Linux其实和Windows一样容易掌握。由于操作和使用环境的陌生,如果要完全熟悉Linux的应用我们首先要解决的问题就是对Linux常用命令的熟练掌握。