linux驱动程序分成三类:字符设备,块设备,网络设备。
字符设备:能像字节流一样访问的设备,通过/dev下的字符设备文件来访问。
块设备:按照块为单位来访问数据,比如一块为512KB,是通过/dev下的文件系统节点来访问的。与字符设备的区别是接口不同,除了提供同字符设备一样的接口外,还提供专门面向块设备的接口,块设备必须支持挂装文件系统,应用程序一般通过文件系统来访问块设备上的内容,而不是直接跟块设备打交道。
网络设备:不使用/dev下的文件节点来操作,而是通过单独的网络接口eth0、eth1等来操作。内核和网络设备的接口不同于字符和块设备,有一套专门的函数。
操作模块的命令:
1 insmod 加载模块
#sudo insmod ./scull.ko
2 rmmod 卸载模块
3 lsmod 列出当前内核使用的模块,或者查看/proc/modules文件
4 depmod 扫描/lib/modules/<kernel version>/目录下的所有内核模块,从而给内核模块生成依赖文件/lib/modules/<kernel version>/modules.dep
5 modprobe 根据depmod生成的modules.dep探测并加载内核模块,只需要给出模块名称自动寻找适合的模块文件,insmod需要给出模块的路径
6 modinfo 查看模块文件的基本信息
#sudo modinfo scull.ko
内核模块的编译方法:
首先要得到内核源代码,并且成功的编译过后生成已编译过的内核源码树,即成功执行过make uImage的内核源码树。然后编写驱动代码后,如果已编译的内核源码树就是此驱动需要运行的内核,则编写Makefile即可将模块代码编译成模块:
ifeq($(KERNELRELEASE),)
KERNELDIR ?= /work/sysbuild/linux-2.6.22.6
PWD:=$(shell pwd)
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
else
obj-m:=hello.o
endif
执行make即可
其中已编译内核源码树目录为:/work/sysbuild/linux-2.6.22.6,模块obj为hello.o,编译后生成hello.ko
最简单的模块例子:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
stataic int hello_init(void)
{
printk("hello world\r\n");
return 0;
}
static void hello_exit(void)
{
printk("goodbye,cruel world\r\n");
}
module_init(hello_init);
module_exit(hello_exit);
可以加载模块时传入参数,使用宏module_param(变量名,变量类型,权限)声明参数,模块运行期间,参数变量会以文件形式出现在/sys目录下,例如#ls /sys/module/hello/parameters/ -l
变量类型有:short,ushort,int,uint,long,ulong,charp,bool
使用方法:
static char *chp="test_char_p";
static int num=1;
module_param(num, int, S_IRUGO|S_IWUSR);
module_param(chp, charp, S_IRUGO);
#insmod hello.ko num=3 chp="test"
把模块集成到内核
1 确保模块工作正常
2 把模块文件hello.c复制到内核的指定目录,例如/drivers/char
3 修改指定目录的Kconfig和Makefile
Kconfig: config HELLO tristate "New Hello"
Makefile: obj -$(CONFIG_HELLO) += hello.o
4 重新配置内核选中将功能编译进内核,而不是编译成模块
5 重新编译内核,得到新内核
6 测试新内核,确保内核模块集成成功
查看系统的设备:
1 查看系统中的字符设备驱动,块设备驱动及其主设备号
#cat /proc/devices
2 查看系统的启动信息
#dmesg
3 查看设备的IO内存物理地址
#cat /proc/iomem
4 查看正在使用的中断号
#cat /proc/interrupts
字符设备驱动体验:
#insmod ./scull.ko
#cat /proc/devices|grep scull
252 scull
#sudo mknod scull0 c 252 0
#sudo chmod 666 scull0
#cat scull0
#sudo echo test>>scull0
#cat scull0
装载scull.ko后寻找这个设备的主设备号,创造这个设备的设备文件(c代表字符设备,0代表第一个从设备号),更改文件属性后操作设备