前几天开始学习编写linux驱动程序,在网上找了几个范例编写,都没有成功,问题一大堆,后又不断摸索,终于在自己的系统下编译通过了hello模块,虽然很简单,但是艰辛呀!
我的linux系统是ubuntu 12.10 ,内核版本是linux version 3.5.0-47-generic,编写的程序如下:
hello.c:
/**********************************************************/
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");/* declare the license of the module ,it is necessary */
static int hello_init(void)
{
printk(KERN_EMERG "hello world there.\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "Hello world exit!\n");
}
module_init(hello_init); /* load the module */
module_exit(hello_exit); /* unload the module */
/* before is some decription of the model,not necessary */
MODULE_AUTHOR("ws");
MODULE_DESCRIPTION("This is an example of programming driver!");
MODULE_ALIAS(“A simplest module”);
/*****************************************************************************/
程序解释如下:
这个模块定义了2个函数,(hello_init)在模块被装载到内核时调用,用insmod命令实现;(hello_exit)在模块被移除时调用,用rmmod命令实现。另外一个特殊宏(MODULE_LICENSE)用来告诉内核,该模块采用自由许可证;如果没有这样的声明,内核在装载该模块时会抱怨(当然不会影响模块的调用)。
编写的Makefile文件如下:
#######################################################
#如果定义了KERNELRELEASE,则说明是从内核构造系统调用的,
#因此可利用其内建语句。
ifneq ($(KERNELRELEASE),)
obj-m +=hello.o
#否则,直接从命令行调用,这时要调用内核构造系统
else
KERNELDIR ?=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean
rm -rf modules.order
endif
########################################################
解释:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
上述命令首先改变目录到-C选项指定的位置(即内核源代码目录),其中保存有内核的顶层makefile文件,M=选项让该makefile在构造modules目标之前返回到模块源代码目录,然后modules指向obj-m变量中设定的模块。
在一个典型的构造中,该makefile将被读取两次,当makefile从命令行调用时,它注意到KERNELRELEASE未设置,则会调用default:目标,这个目标第二次运行make命令(注意,这里make命令被参数化了$(MAKE))。
clean:这个目标表示将模块清理掉
然后执行make命令,会生成很多文件,其中有一个hello.ko文件,下面将用到:
执行 sudo insmod ./hello.ko
我的终端并没有产生任何输出,然后执行
dmesg命令,就可以看到输出了:hello world there.
执行sudo rmmod hello 显示hello world exit.