要进行驱动编程,首先要构造内核树,其实就是安装一堆的头文件,具体方法如下,使用本地yum源安装
yum search kernel-devel
sudo yum install kernel-devel.x86_64
我的电脑装的是FC16,64位,因此需要的是X86-64,如果是32bit系统,那么在search的结果中找到你系统版本对应的那个包,使用命令uname -r查看系统版本。安装成功后,在/usr/src/kernels/3.1.0-7.fc16.x86_64可以看到内核树。这个内核树里头是没有各种实现的.c文件的,如果想要看驱动的具体实现的话,可以查看我的另一篇文章http://blog.chinaunix.net/uid-24943863-id-3184481.html
现在可以开始一个hello world程序了。在/home目录下建立一个工作空间,编写ktest.c和Makefile如下:
- 1 #include<linux/module.h>
- 2 #include<linux/init.h>
- 3
- 4 MODULE_LICENSE("Dual BSD/GPL");
- 5
- 6 static int __init helloinit()
- 7 {
- 8 printk("hello Fedora!\n");
- 9 return 0;
- 10 }
- 11
- 12 static void __exit helloexit()
- 13 {
- 14 printk("good bye fedora!\n");
- 15 }
- 16
- 17 module_init(helloinit);
- 18 module_exit(helloexit);
MODULE _LICENSE()是许可证声明,通常使用GPL/DUAL BSD,最好进行自由许可证的声明,否则内核会抱怨的。module_init()和module_exit()是必须的,用来通知内核模块已经准备就绪,可以使用,或者模块已经卸载,不能调用了。这两个函数里头分别填初始化程序和清理函数的函数名。static是本地属性,表示其他文件不能够调用本函数,elf文件的symtab符号表这个函数出现FUNC LOCAL属性,在gcc编译的时候,如果有其他.c文件的函数调用这个.c文件的static属性函数的话会出现符号不能解析的错误。__init和__exit是用来告诉内核这个函数只会调用一次,调用完了就可以扔掉了。printk是内核的打印信息的工具,类似于userspace的printf函数,差别在于printk不能打印很长的字符串,且只能打印整数,不支持浮点数。
- ifneq ($(KERNELRELEASE),)
- obj-m:=ktest.o
- else
- KERNELDIR ?= /lib/modules/$(shell uname -r)/build
- PWD:=$(shell pwd)
- default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
- endif
- .PHONY:clean
- clean:
- rm *.ko *.mod.c *.o *.order *.symvers
这里注意Makefile的命令必须以tab键开始。
接下来make,生成的ktest.ko就是我们要的模块了。obj-m是告诉gcc编译成模块,依赖ktest.o。KERNELDIR变量用来存储内核的源码树路径,PWD变量存储的是ktest.c所在的目录.$(MAKE)是带有参数的make命令,-C选项是告诉gcc用KERNELDIR的Makefile,那个目录下的Makefile执行实际的模块构造,-M选项将输出放到PWD下。
执行安装和卸载模块命令
- cd ~/workSpace/ktest
- su
- insmod ktest.ko
- rmmod ktest.ko
现在可以用cat / var/log/messages命令查看内核的printk消息。
现在可以开始内核之旅了!
阅读(2611) | 评论(0) | 转发(1) |