Linux设备驱动概述
以点亮LED为例:包括应用程序、库、操作系统、内核、驱动程序。而开发人员中
只要关注自己的那一层,相邻层只关注接口就可以了
1,应用程序使用库提供的open函数打开LED的设备文件
2,库根据open函数传入的参数执行“SWI”指令,这是软中断,这条指令会引起
CPU异常,进入内核
3,内核异常处理函数就会根据这些参数找到相应的驱动程序,返回一个
句柄给库,进而返回给应用程序
4,应用程序得到句柄后,使用库提供的write和ioctl函数发出控制指令
5,库根据write和ioctl函数传入的参数执行“SWI”指令,再次引起CPU异常
进入内核
6,内核根据异常处理函数根据这些参数调用驱动程序的相关函数,点亮LED
在异常处理函数中,内核会根据传入的参数执行各种操作,比如根据设备文件名
找到对应的驱动程序,调用驱动程序的相关函数
另外,驱动程序从不主动运行,都是被动运行,但也不是绝对的,用户完全可以
写一个由系统时钟触发的驱动,让它自动点亮LED
再者,应用程序运行在“用户空间”,拥有MMU的系统能够限定应用程序的权限,只
运行在某指定内存块当中,可以避免应用程序的错误导致系统崩溃,
而驱动程序是运行在内核态的,这是系统信任的一部分,驱动程序有错误可能
导致整个系统崩溃,呵呵,小心了呀
三种驱动类型的点滴
1,字符型设备,收发是以字节为单位进行的,驱动程序要实现
open,read,write,close等系统调用
2,块设备,数据是以块的形式进行存放,如NAND Flash上以页为单位进行存放
同时,驱动程序向用户提供的接口与字符型设备一样,对用户而言,块设备
和字符设备的访问方式是相同的。
区别在于,块设备驱动程序先将用户发送的数据组织成块,再写入设备,或是从设备中
读入若干块数据,再从中挑出用户需要的。
数据块上的数据可以有一定的格式。不同的文件系统就是用来定义这种格式的。
3,网络设备兼具两种驱动的特点,它的输入与输出是有结构的,不像字符型驱动
同时,传送的数据大小不等。另外,应用程序、内核和网络驱动程序间的通信
完全不同于,字符设备和块设备,库、内核提供了一套和数据包传输相关的函数
而不是open,close,read,write等。
驱动程序的开发步骤:
大致流程如下:
1,查看原理图,数据手册,大致了解硬件的操作方法
2,在内核中的找到相近的驱动程序,以此为模板进行开发,有时候需要从0开始
3,实现驱动的初始化,比如向内核注册这个驱动程序,这样应用调用时,内核才
能找到这个驱动程序
4,设计所要操作的实现,如open,clos,read,write等函数
5,实现中断服务,但不是每个程序所必须的
6,编译到内核或动态的加载
7,测试驱动程序
注意点:
1,在Linux内核源码中大约有85%都是驱动
2,驱动编写的难点不是硬件的具体操作,而是弄清楚驱动程序的框架
3,驱动程序可以同时被好几个进程使用,要考虑到并发的问题
4,该不该使用DMA,可以用也可以不用,使用可以提高效率,但是程序比较复杂。
5,在2.6内核中模块的文件名为.ko,可以使用insmod加载,使用rmmod缷载
可以使用lsmod来查看加载的模块。
6,并不是只有驱动才可以编译成模块,文件系统也可以编译成模块的。