1.驱动介绍Linux驱动本质上是一个软件程序。上层软件可以在不知道硬件特性的情况下,通过驱动程序提供的接口与计算机硬件进行通信。系统调用是内核和应用程序之间的接口,而驱动程序是内核和硬件之间的接口。它为应用程序屏蔽了硬件细节,所以对于应用程序来说,硬件设备只是一个设备文件,应用程序可以像普通文件一样操作硬件设备。Linux驱动只是内核的一部分,管理着系统的设备控制器和相应的设备。Driver,英文名称为“DeviceDriver”,全称“DeviceDriver”,是一种使计算机能够与设备进行通信的特殊程序。相当于硬件的接口。只有通过这个接口,操作系统才能控制硬件设备的工作。它主要完成以下功能:初始化和释放设备,向硬盘传输数据和从硬件读取数据,检测和处理设备错误。2、驱动分类计算机系统的硬件由CPU、内存、外围设备组成。驱动程序的目标是内存和外围设备。Linux将外围设备和内存分为三个基本类别:块设备驱动程序、字符设备驱动程序和网络设备驱动程序。2.1.字符设备驱动字符设备是指必须按串行顺序访问的设备,字符设备的I/O操作不经过缓存。字符设备操作是基于字节的,但一次只能执行一个字节的操作。典型的如LCD、串口、LED、蜂鸣器、触摸屏等。2.2.块设备驱动块设备是相对于字符设备定义的,可以任意顺序访问,以块为单位进行操作。块设备驱动的读写是靠一个缓存来支持的,块设备必须是可以随机访问的。设备的块大小在设备本身设计时定义,软件无法更改。不同设备的块大小可以不同。常见的块设备是存储设备,如:硬盘、NandFlash、iNand、SD等。2.3.网络设备驱动网络设备驱动是专门为网卡设计的驱动模型,它是为数据包的接收和发送而设计的,不应该用于文件系统的节点。即不对应/dev目录下的设备文件,应用程序最终使用socket字来完成与网络设备的接口。Linux文件系统中除了网络设备外,字符设备和块设备都被映射到文件和目录中,字符设备可以通过文件系统调用接口open()、write()、read()、close()等和块设备。块设备比字符设备更复杂。首先会在其上建立磁盘/Flash文件系统,如FAT、EXT3、TAFFS、TFFS等。FAT、EXT3、TAFFS、TFF规范了文件和目录在存储介质上的组织方式。3、驱动程序的编译和加载Linux设备驱动程序是内核的一部分。Linux内核的一个模块可以通过两种方式编译和加载。外部编译:在内核源码目录外编译驱动源码。3.2.加载方式静态加载:编译成uImage,系统启动时直接加载。动态加载:编译.ko文件,动态加载驱动模块。3.3.编译器x86等架构可以使用gcc,arm嵌入式设备需要使用相关的交叉编译工具链。下面是一个内核模块的例子:#include//所有模块需要的头文件#include//init&exit相关宏staticint__inithello_init(void){printk("你好模块初始化\n");返回0;}staticvoid__exithello_exit(void){printk("Hello模块退出\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("LYB");MODULE_DESCRIPTION("linux驱动测试");分析上述程序,发现一个Linux内核模块需要包含模块初始化和模块卸载功能,前者在insmod时运行,后者在rmmod时运行。初始化和卸载函数必须在使用宏module_init和module_exit之前定义,否则会出现编译错误。初始化和卸载函数必须在使用宏module_init和module_exit之前定义,否则会出现编译错误。程序中:MODULE_LICENSE("GPL")用于声明模块的许可证。MODULE_AUTHOR:描述作者信息..MODULE_DESCRIPTION:此驱动程序的说明。如果想直接编译进Linux内核,需要将源代码文件复制到Linux内核源代码对应的路径下,修改Makefile。模块初始化函数的任务是为以后调用模块的函数做准备,就好像模块在说,“我来了,这就是我能做的”。卸载模块时调用模块的退出函数(示例中的hello_exit)。它似乎在告诉内核,“我不在了,不要要求我做任何事情”。这种编程方法类似于事件驱动编程,但虽然并非所有应用程序都是事件驱动的,但每个内核模块都是。事件驱动应用程序和内核代码之间的另一个主要区别是退出函数:终止的应用程序可以懒惰地释放资源,或者根本不进行清理,但是模块的退出函数必须小心恢复由初始化函数,否则在系统重新启动之前会保留一些内容。写Makerfile编译:KERN_DIR?=/usr/src/linux-headers-$(shelluname-r)/#kernel源码目录/usr/src/linux-headers-$(shelluname-r)/PWD:=$(shellpwd)obj-m:=driverTest.koall:make-C$(KERN_DIR)M=$(PWD)modulesclean:make-C$(KERN_DIR)M=$(PWD)clean3.4,驱动加载,卸载和debuginsmod./hello.ko//加载驱动lsmod//查看加载的驱动lsmod|grephello//使用grep搜索过滤demsg//查看内核打印信息demsg|grephello//使用grep过滤信息rmmodhello//卸载驱动