嵌入式Linux驱动程序开发要点(20210201123523)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
嵌入式Linux驱动程序开发要点
在Linux操作系统下有3类主要的设备文件类型:块设备、字符设备和网络设备。这种分类方法可以将控制输入/输出设备的驱动程序与其他操作系统软件分离开来。|字符设备与块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件
I/O 一般紧接着发生。块设备则不然,它利用一块系统内存作为缓冲区,若用户进程对设备的请求能满足用户的要求,就返回请求的数据;否则,就调用请求函数来
进行实际的I/O操作。块设备主要是针对磁盘等慢速设备设计的,以免耗费过多的CPU时间用来等待。网络设备可以通过BSD套接口访问数据。
每个设备文件都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有2个设备号,第一个是主设备号,标识驱动程序;第二个是从设备号,标识使用同一个设备驱动程序的、不同的硬件设备。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问驱动程序。
系统调用时操作系统内核与应用程序之间的接口,设备驱动程序是操作系统内核
与机器硬件之间的接口。设备驱动程序是内核的一部分,它完成以下功能:
•对设备初始化和释放
•把数据从内核传送到硬件和从硬件读取数据
•读取应用程序传送给设备文件的数据和回送应用程序请求的数据
•佥测和处理设备出现的错误
MTD(Memory
Tech no logy
Device )设备是闪存芯片、小型闪存卡、记忆棒之类的设备,它们在嵌入式设备中的使用正在不断增加。MTD驱动程序是在Linux下专门为嵌入式环境开发的新的一类驱动程序。相对于常规块设备驱动程序,使用MTD驱动程序的
优点在于他们能更好的支持、管理给予闪存设备,有基于扇区的擦除和读/写操作的
更好的接口。
驱动程序结构
Linux的设备驱动程序可以分为3个主要组成部分:
1. 自动配置和初始化子程序,负责监测所要驱动的硬件设备是否存在和能否正常工作。如果该设备正常,则对这个设备及其相关的设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化时被调用一次。
2.
服务于I/O请求的子程序,又称为驱动程序的上半部分。调用这部分程序是由于系统调用的结果。这部分程序在执行时,系统仍认为是与进行调用的进程属于同个进程,只是由用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因而可以在其中调用sleep()等与进行运行环境有关的函数。
3.
中断服务子程序,又称为驱动程序的下半部分。在Linux系统中,并不是直接从
中断向量表中调用设备驱动程序的中断服务子程序,而是由Linux系统来接
收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个进程运行时产
生,因而在中断服务程序被调用时,不能依赖于任何进程的状态,也就不能调用任何
与进程运行环境有关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务子程序时,都带有一个或多个参数,以唯一标识请
求服
务的设备。
在系统内部,I/O设备的存/取通过一组固定的入口点来进行,这组入口点是由每
个设备的驱动程序提供的。具体到Linux系统,设备驱动程序所提供的这组入口
点由一个文件操作结构来向系统进行说明。file_operation结构定义于linux/fs.h
文件中。
struct file_operati on{
int (*lseek)(struct inode *inode, struct file *filp, off_t off, int pos);
int (*read)(struct inode *ino de, struct file *filp, char *buf, i nt coun t);
int (*write)(struct inode *ino de, struct file *filp, const char *buf, i nt coun t);
int (*open)(struct inode *inode, struct file *filp);
int (*release)(struct inode *inode, struct file *filp);
用户自己的驱动程序中,首先要根据驱动程序的功能,完成file_operation结构中函数实现。不需要的函数接口可以直接在
int (*fasync)(struct inode *inode, struct file *filp);
};
file_operation结构中的成员几乎全部是函数指针,所以实质上就是函数跳转表。
每个进程对设备的操作都会根据major、mi nor设备号,转换成对file_operation
结构的访问。
常用的操作包括以下几种:
•l seek移动文件指针的位置,只能用于可以随机存取的设备。
•read,进行读操作,参数buf为存放读取结果的缓冲区,count为所要读取的数据长度。返回值为负表示读取操作发生错误;否则,返回实际读取的字节数。对
于字符型,要求读取的字节数和返回的实际读取字节数都必须是in ode-i_blksize 的倍数。
• write,进行写操作,与read类似
•r eaddir,取得下一个目录入口点,只有与文件系统相关的设备程序才使用。•select进行选择操作。如果驱动程序没有提供select入口,select操作会认为设备已经准备好进行任何I/O操作。
†ioctl,进行读、写以外的其他操作,参数cmd为自定义的命令
•m map,用于把设备的内容映射到地址空间,一般只有块设备驱动程序使用•open,打开设备准备进行I/O操作。返回0表示打开成功,返回负数表示失败。如果驱动程序没有提供open入口,则只要/dev/driver文件存在就认为打开成功。
•r elease即close 操作。
在
void kfree(void *obj);
参数len为希望申请的字节数;obj为要释放的内存指针;priority为分配内存操作的优先级,即在没有足够空闲内存时如何操作,一般用GFP_KERNEL。