PCI驱动编程基本框架

合集下载

PCI编程指南

PCI编程指南

PCI编程指南【认识PCI】PCI是一种总线的名称,英文全称为Peripheral Component Interconnect。

PCI局部总线是微型计算机上处理器/存储器与外围控制部件、外围附加板之间的互连机构。

打开你的PC机箱,即可看到PCI插槽。

俺的PC里还有一个ISA插槽,好像现在的PC机都只有PCI插槽了。

PCI技术最初由Intel在1995年提出,所以它是little endian的。

PCI标准规范由PCI SIG组织维护,不过这个规范可不是免费的。

基本的PCI接口规范是3V、33MHz、32位总线,数据传输速率是133Mb/s。

PCI还有其它的扩展:64位总线扩展:数据传输速率为266Mb/s;66MHz扩展等。

AGP:Accelerated Graphics Port,专门为视频卡设计。

PC机里插显卡的那个槽就是AGP槽了。

66MHz,最大传输速率可达1064Mb/s。

从编程角度看AGP完全等效于PCI。

cPCI:Compact PCI。

一种基于PCI标准的高性能工业总线。

和标准桌面的PCI相比,cPCI 提供2倍的PCI插槽(8:4),并提供热插拔机制,更适合于工业应用。

从编程角度看CPCI 完全等效于PCI。

工业上的PCI/cPCI机箱价格不菲,有的高达几万美金。

PXI:PXI规范是NI公司1997年9月1日发布的一种新的开放性、模块化仪器总线规范,是PCI总线在仪器领域的扩展。

/whatnew/pxi.htm【PCI编程概念】PCI设备是真正的“plug-and-pl ay”。

PCI设备的参数可以被程序动态地读写。

可配置的参数出现在PCI配置空间中。

PCI设备可以访问三类地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。

(参考《Linux编程白皮书》、《Linux设备驱动程序》。

)memory space实际上是和内存统一编址的,用普通的C语句就可以访问。

x86 CPU能够使用inb/outb等指令访问I/O空间;PowerPC则需要把设备的寄存器映射到内存空间中,进行统一编址。

一、如何编写LinuxPCI驱动程序

一、如何编写LinuxPCI驱动程序

⼀、如何编写LinuxPCI驱动程序PCI的世界是⼴阔的,充满了(⼤部分令⼈不快的)惊喜。

由于每个CPU体系结构实现不同的芯⽚集,并且PCI设备有不同的需求(“特性”),因此Linux内核中的PCI⽀持并不像⼈们希望的那么简单。

这篇简短的⽂章介绍⽤于PCI设备驱动程序的Linux APIs。

1.1 PCI驱动程序结构PCI驱动程序通过pci_register_driver()在系统中"发现"PCI设备。

事实上,恰恰相反。

当PCI通⽤代码发现⼀个新设备时,具有匹配“描述”的驱动程序将被通知。

详情如下。

pci_register_driver()将设备的⼤部分探测留给PCI层,并⽀持在线插⼊/删除设备[因此在单个驱动程序中⽀持热插拔PCI、CardBus和Express-Card]。

pci_register_driver()调⽤需要传⼊⼀个函数指针表,从⽽指⽰驱动程序的更⾼⼀级结构体。

⼀旦驱动程序知道了⼀个PCI设备并获得了所有权,驱动程序通常需要执⾏以下初始化:启⽤设备请求MMIO / IOP资源设置DMA掩码⼤⼩(⽤于⼀致性DMA和流式DMA)分配和初始化共享控制数据(pci_allocate_coherent())访问设备配置空间(如果需要)注册IRQ处理程序(request_irq())初始化non-PCI(即LAN/SCSI/等芯⽚部分)启⽤DMA /处理引擎当使⽤设备完成时,可能需要卸载模块,驱动程序需要采取以下步骤:禁⽌设备产⽣irq释放IRQ (free_irq())停⽌所有DMA活动释放DMA缓冲区(包括流式DMA和⼀致性DMA)从其他⼦系统注销(例如scsi或netdev)释放MMIO / IOP资源禁⽤该设备下⾯⼏节将介绍这些主题中的⼤部分。

其余部分请查看LDD3或<linux/pci.h>。

如果PCI⼦系统没有配置(没有设置CONFIG_PCI),下⾯描述的⼤多数PCI函数都被定义为内联函数,要么完全空,要么只是返回⼀个适当的错误代码,以避免在驱动程序中出现⼤量ifdefs。

基于pci-e总线的加密网卡驱动及应用程序设计

基于pci-e总线的加密网卡驱动及应用程序设计

AbstractWith the rapid development of Internet technology, the security issues of network information become acute increasingly. Network information security should be a height priority to protect people's livelihood, national security in this era of global Internet.A hardware encryption network card is designed to keep network information security. To ensure network information security, the user data was encrypted and then transmitted through the public Internet. The driver and application of encryption network card in the Linux system was discussed in this paper.This program is based on Ubuntu16.04 system, Linux4.4 kernel. The application is based on Qt. This paper introduces the knowledge about Linux driver, TCP/IP protocol, PCI-e and DMA first, as well as the hardware structure of the encryption card. And then discuss the study of the encryption network card application system, focusing on the design of encryption card driver and the application. Int the end of the paper, the test of the driver and the application will be talked about.Encryption card is a low-cost efficient solutions to keep network information security. Developping drivers and applications base on the Linux system conform to the the ideological line to develop domestic operating system based on the Linux kernel under the background of vigorously developping domestic operating system, and conducive to the promotion of Linux system. When the domestic operating system matures and promote the use, it is easy to transplant the program into the domestic operating system.Keywords: encryption network card; Linux; driver; application; PCI-e;DMA目 录中文摘要 (I)Abstract ............................................................................................................................. I I 第1章绪论 . (1)1.1 课题研究的背景 (1)1.2 课题研究的意义 (2)1.3 国内外研究现状 (3)1.4 论文的内容及组织结构 (4)第2章基础知识 (6)2.1 Linux驱动程序概述 (6)2.1.1 Linux驱动程序的分类 (6)2.1.2 Linux设备驱动的模块化 (7)2.2 TCP/IP协议介绍 (7)2.2.1 以太网数据封装 (7)2.2.2 以太网首部 (8)2.2.3 IP协议首部 (9)2.2.4 UDP协议首部 (10)2.2.5 TCP协议首部 (10)2.3 PCI-e/PCI总线 (11)2.3.1 PCI/PCI-e设备的初始化过程 (12)2.3.2 PCI-e总线配置空间 (14)2.3.3 PCI-e的MSI中断 (17)2.4 PCI/PCI-e设备DMA传输分析 (18)2.5 加密网卡硬件结构介绍 (19)2.5.1 加密网卡总体结构介绍 (19)2.5.2 FPGA数据接收发送链路结构介绍 (21)2.6 本章小结 (21)第3章加密网卡应用系统设计 (22)3.1 系统总体结构设计 (22)3.2 驱动程序结构设计 (23)3.2.1 驱动程序功能模块设计 (23)3.2.2 数据加密设计 (24)3.3 应用程序结构设计 (25)3.3.1 应用程序server端设计 (25)3.3.2 应用程序client端设计 (26)3.3.3 应用层数据封包格式设计 (28)3.4 本章小结 (28)第4章驱动程序设计 (29)4.1 驱动程序加载和卸载 (29)4.1.1 PCI-e驱动程序和设备的匹配 (29)4.1.2 PCI-e驱动程序的加载和卸载 (30)4.1.3 设备初始化和关闭 (31)4.2 Linux下的DMA编程 (34)4.2.1 DMA地址掩码 (35)4.2.2 DMA地址映射 (36)4.3网络设备的注册和初始化 (38)4.3.1 网络设备的注册和移除 (38)4.3.2 网络设备初始化流程 (39)4.4 网络设备的打开和关闭 (41)4.5 网络设备中断处理设计 (43)4.6 网络数据的接收和发送 (44)4.6.1 struct sk_buff结构体 (44)4.6.2 数据发送流程 (46)4.6.3 数据接收流程 (50)4.7 物理链路连接状态检测 (52)4.8 字符设备程序设计 (54)4.8.1 字符设备注册 (55)4.8.2 字符设备操作方法设计 (56)4.9 本章小结 (58)第5章应用程序设计 (59)5.1 视频及文件传输程序设计 (59)5.1.1 应用层协议设计 (59)5.1.2 client端与server端连接的建立流程 (62)5.1.3 视频码流处理框架设计 (63)5.1.4 环形缓冲区的设计 (64)5.1.5 视频传输流程设计 (68)5.1.6 文件传输流程设计 (69)5.2 秘钥管理程序设计 (70)5.3 系统测试 (71)5.3.1 网卡传输速率测试 (71)5.3.2 数据加密传输测试 (74)5.4 本章小结 (76)结论 (77)参考文献 (78)致谢 (84)攻读硕士学位期间发表的学术论文 (85)独创性声明 (86)第1章绪论1.1 课题研究的背景进入21世纪以来,互联网技术得到了长足的发展和进步。

PCIExpress系统体系结构标准教材

PCIExpress系统体系结构标准教材

PCIExpress系统体系结构标准教材第1章体系结构展望1.1 第⼀代总线:ISA,EISA,VESA第⼆代总线:PCI, AGP, PCI-X第三代总线:PCIE1.2 PCIE的存储器、IO和配置地址空间与PCI和PCI-X的地址空间相同。

现有的驱动⽆需改动可以在PCIE运⾏中断控制器在南桥33MHz的PCI峰值带宽为4KB*33=133MB/s1.3 I/O总线体系结构1) PCI设备使⽤4个中断信号(INTA#,B,C,C) 触发中断控制器的中断请求,然后中断控制器向CPU声明INTR信号2) 3种类型的地址空间配置地址空间:每个PCI功能最多有256B, CPU通过北桥的IO映射数据和地址端⼝间接访问配置空间3)最新⼀代的intel PCI芯⽚组,把南北桥换成了MCH, ICH4)PCI-X ⽐PCI 频率更⾼,PCI-X设备可以插⼊PCI插槽,反之亦然。

PCI-X 峰值达到1064MB/s第2章体系结构概述2.1 PCIE 事务通信涉及处理层数据包(Transaction Layer packet, TLP) 的收发PCIE事务包括:1)存储器事务,2)IO事务,3)配置事务,4)消息事务2.2 PCIE的设备层有处理层,数据链路层,物理层;对应的数据包为TLP, DLLP, PLP1)处理层有虚拟信道缓冲区(VC缓冲区),流控,TLP排序,QoS也在此层(PCI不⽀持QoS);缓冲区⽤于数据的收发,流控避免缓冲区溢出;流控是硬件⾃动管理的;QoS 指的是以不同的优先级,确定的延迟及带宽路由不同应⽤程序的数据包通过结构的能⼒。

如视频对时间要求⾼,SCSI对正确性要求⾼,所以视频数据包的优先级⾼。

VC仲裁会优先通过视频数据包 2)流量类别TC,是数据包的⼀个TLP头字段, TC会映射到虚拟信道VC可实现最多8个VC缓冲区,2.3 ⾮报告存储器读事务两个阶段:请求者发送存储器读请求TLP给完成者;接收来⾃完成者的带数据的完成。

PCIE驱动开发流程

PCIE驱动开发流程

#ifdef CONFIG_PM
.suspend = xxx_pm_suspend,
.resume = xxx_pm_resume,
#endif /* CONFIG_PM */
};
结构体中 name 指明 PCIE 模块的名称,id_table 指明了 PCIE 的设备驱动号也
就是为哪个设备进行驱动等。
PCIE 开发流程
前言:对于 USB、PCIE 设备这种挂接在总线上的设备而言,USB、PCI 只是它们 的”工作单位”,它们需要向”工作单位”注册(使用 usb_driver,pci_driver),并接 收 ” 工 作 单 位 ” 的 管 理 ( 被 调 入 probe() 、 调 出 disconnect/remove() 、 放 假 suspend()/shutdown()、继续上班 resume()等),但设备本身可能是一个工程师、 一个前台或者一个经理,因此做好工程师,前台或者经理是其主题工作,这部分 对应于字符设备驱动,tty 设备驱动,网络设备驱动等。
对于 linux 来说这些调用都会变成系统调用,并指向改设备对应的 open(),read()
函数,对于该设备来说,指向了 xxx_open 和 xxx_read。
static struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.llseek
第二节 PCIE 设备实现细节
由于 PCIE 设备的驱动的开发都是按照一个统一规范的框架进行的。因此以一 个字符设备为例说明这个框架的实现机制。在所有 PCIE 驱动开发的过程中 2.1 驱动程序的初始化和注销
涉及的பைடு நூலகம்数为 module_init(xxx_init_module),并在 init 中完成的功能为注册 PCIE 设备,具体函数内容如下所示:

PCI驱动编程

PCI驱动编程

目录一、字符设备和块设备 (2)二、设备驱动程序接口 (2)三、设备驱动程序模块 (3)四、设备驱动程序结构 (4)1.驱动程序的注册与注销 (4)2.设备的打开与释放 (4)3.设备的读写操作 (4)4.设备的控制操作 (5)5.设备的中断和轮询处理 (5)五、PCI驱动程序框架 (5)1.关键数据结构 (5)a. pci_driver (5)b. pci_dev (6)2.基本框架 (9)六、框架的具体实现之模块操作 (12)1.struct pci_device_id (12)2.初始化设备模块 (12)3.卸载设备模块: (15)4.中断处理: (16)七、框架的具体实现之设备文件操作 (16)1.设备文件操作接口 (16)2.打开设备模块 (17)3.释放设备模块 (17)4.设备数据读写和控制信息模块 (18)5.内存映射模块 (19)八、附录 (19)1.PCI设备私有数据结构 (19)2.PCI配置寄存器 (20)参考资料: (21)一、字符设备和块设备Linux抽象了对硬件的处理,所有的硬件设备都可以像普通文件一样来看待:它们可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,而驱动程序的主要任务也就是要实现这些系统调用函数。

Linux系统中的所有硬件设备都使用一个特殊的设备文件来表示,例如,系统中的第一个IDE硬盘使用/dev/hda表示。

每个设备文件对应有两个设备号:一个是主设备号,标识该设备的种类,也标识了该设备所使用的驱动程序;另一个是次设备号,标识使用同一设备驱动程序的不同硬件设备。

设备文件的主设备号必须与设备驱动程序在登录该设备时申请的主设备号一致,否则用户进程将无法访问到设备驱动程序。

在Linux操作系统下有两类主要的设备文件:一类是字符设备,另一类则是块设备。

字符设备是以字节为单位逐个进行I/O操作的设备,在对字符设备发出读写请求时,实际的硬件I/O紧接着就发生了,一般来说字符设备中的缓存是可有可无的,而且也不支持随机访问。

PCie 驱动

PCie 驱动

PCie驱动Pcie设备上有三种地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。

Pce的配置空间:PCI有三个相互独立的物理地址空间:设备存储器地址空间、I/O地址空间和配置空间。

配置空间是PCI 所特有的一个物理空间。

由于PCI支持设备即插即用,所以PCI设备不占用固定的内存地址空间或I/O地址空间,而是由操作系统决定其映射的基址。

系统加电时,BIOS检测PCI总线,确定所有连接在PCI总线上的设备以及它们的配置要求,并进行系统配置。

所以,所有的PCI设备必须实现配置空间,从而能够实现参数的自动配置,实现真正的即插即用。

PCI总线规范定义的配置空间总长度为256个字节,配置信息按一定的顺序和大小依次存放。

前64个字节的配置空间称为配置头,对于所有的设备都一样,配置头的主要功能是用来识别设备、定义主机访问PCI卡的方式(I/O访问或者存储器访问,还有中断信息)。

其余的192个字节称为本地配置空间,主要定义卡上局部总线的特性、本地空间基地址及范围等。

一般来说,基于pcie总线的驱动,需要涉及到pci_driverpci_devpci_device_id.pci_device_id:用于标识pcie设备,通过上图的厂商Id设备Id功能号等唯一确定一个pcie设备,内核通过这个结构体确认驱动与设备是否匹配。

pci_dev:一般pcie设备都具有热拔插功能,当内核检测到有pcie设备插入时,会与相应的Pci_driver:当有相应的设备匹配会调用驱动的相关方法,驱动中通常要做的是读出Base AdrressRegister1-6的值,这是pcies设备6个内存空间的基地址,然后通过ioremap方法映射成虚拟地址,至于6个内存空间的具体含义需要依赖于设备。

在用模块方式实现PCI设备驱动程序时,通常至少要实现以下几个部分:初始化设备模块、设备打开模块、数据读写和控制模块、中断处理模块、设备释放模块、设备卸载模块。

PCI驱动程序的设计

PCI驱动程序的设计

/+当驱动程序卸除某个设备时被调用的函数指针 +/
it( s v _ tt ( tu t c_ e d v u tt : n a esa e) src i v p d e , 32sae)
/+ 在挂起前存储设备状态 +/
it( s s e d) s rc c d v }d v u 2 sae) n u p n ( tu tp i e _ e , 3 tt :
驱动程序 都有一个 pi ei _ c d v ei _ c d的数组 ,用 于告 诉 P I C 核心能
够 驱 动 哪 些 设 备 。N 20 E 0 0驱 动 程 序 的 pi ei _ c dv ei 组 为 _ c. d数
n 2 e t l ] e ii a 。 ekpib 【_ v t t _ _ nda d
对 于 基 于 P I 备 的 网 卡 驱 动 程 序 来 说 ,应 该 为 每 一 个 网 C设 卡创建一个 pire结构 。 c d vr _i s ut e d vr 结 构 为 : t epif e的 r i
s r c c dr e { tu tp i i r v
_
/ 厂商和设备 I D号或者 P L N J C A Y D+/
it ( en bl_ k )(tu tp i e d v 3 tt .it n n a e wa e s rc c_ v d e 。u 2 sae n — e

编 写 P 驱 动 程 序 CI
对 于 P I 动 的 编写 有 两 种 架 构 ,一 种 是 设 备 驱 动 程 序 自 C驱
关 键词
探 测 函数 ,I 0地 址 ,注册 设备 /
P I 外 围 设 备 互 连 ( e pea C mpnn Itr n et C是 Pr hrl o oet nec nc) i o
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux将所有外部设备看成是一类特殊文件,称之为“设备文件”,如果说系统调用是Linux 内核和应用程序之间的接口,那么设备驱动程序则可以看成是Linux内核与外部设备之间的接口。

设备驱动程序向应用程序屏蔽了硬件在实现上的细节,使得应用程序可以像操作普通文件一样来操作外部设备。

1. 字符设备和块设备Linux抽象了对硬件的处理,所有的硬件设备都可以像普通文件一样来看待:它们可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作,而驱动程序的主要任务也就是要实现这些系统调用函数。

Linux系统中的所有硬件设备都使用一个特殊的设备文件来表示,例如,系统中的第一个IDE硬盘使用/dev/hda表示。

每个设备文件对应有两个设备号:一个是主设备号,标识该设备的种类,也标识了该设备所使用的驱动程序;另一个是次设备号,标识使用同一设备驱动程序的不同硬件设备。

设备文件的主设备号必须与设备驱动程序在登录该设备时申请的主设备号一致,否则用户进程将无法访问到设备驱动程序。

在Linux操作系统下有两类主要的设备文件:一类是字符设备,另一类则是块设备。

字符设备是以字节为单位逐个进行I/O操作的设备,在对字符设备发出读写请求时,实际的硬件I/O紧接着就发生了,一般来说字符设备中的缓存是可有可无的,而且也不支持随机访问。

块设备则是利用一块系统内存作为缓冲区,当用户进程对设备进行读写请求时,驱动程序先查看缓冲区中的内容,如果缓冲区中的数据能满足用户的要求就返回相应的数据,否则就调用相应的请求函数来进行实际的I/O操作。

块设备主要是针对磁盘等慢速设备设计的,其目的是避免耗费过多的CPU时间来等待操作的完成。

一般说来,PCI卡通常都属于字符设备。

2. 设备驱动程序接口Linux中的I/O子系统向内核中的其他部分提供了一个统一的标准设备接口,这是通过include/linux/fs.h中的数据结构file_operations来完成的:struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*aio_fsync) (struct kiocb *, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **);long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);};当应用程序对设备文件进行诸如open、close、read、write等操作时,Linux内核将通过file_operations结构访问驱动程序提供的函数。

例如,当应用程序对设备文件执行读操作时,内核将调用file_operations结构中的read函数。

3. 设备驱动程序模块Linux下的设备驱动程序可以按照两种方式进行编译,一种是直接静态编译成内核的一部分,另一种则是编译成可以动态加载的模块。

如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态地卸载,不利于调试,所有推荐使用模块方式。

从本质上来讲,模块也是内核的一部分,它不同于普通的应用程序,不能调用位于用户态下的C或者C++库函数,而只能调用Linux内核提供的函数,在/proc/ksyms中可以查看到内核提供的所有函数。

在以模块方式编写驱动程序时,要实现两个必不可少的函数init_module( )和cleanup_module( ),而且至少要包含和两个头文件。

一般使用LDD3 例程中使用的makefile 作为基本的版本,稍作改变之后用来编译驱动,编译生成的模块(一般为.ko文件)可以使用命令insmod载入Linux内核,从而成为内核的一个组成部分,此时内核会调用模块中的函数init_module( )。

当不需要该模块时,可以使用rmmod命令进行卸载,此进内核会调用模块中的函数cleanup_module( )。

任何时候都可以使用命令来lsmod查看目前已经加载的模块以及正在使用该模块的用户数。

4. 设备驱动程序结构了解设备驱动程序的基本结构(或者称为框架),对开发人员而言是非常重要的,Linux的设备驱动程序大致可以分为如下几个部分:驱动程序的注册与注销、设备的打开与释放、设备的读写操作、设备的控制操作、设备的中断和轮询处理。

驱动程序的注册与注销向系统增加一个驱动程序意味着要赋予它一个主设备号,这可以通过在驱动程序的初始化过程中调用register_chrdev( )或者register_blkdev( )来完成。

而在关闭字符设备或者块设备时,则需要通过调用unregister_chrdev( )或unregister_blkdev( )从内核中注销设备,同时释放占用的主设备号。

但是现在程序员都倾向于动态创建设备号和设备结点,动态创建设备号和设备结点需要几个指定的函数,具体可以参见“Linux字符驱动中动态分配设备号与动态生成设备节点”。

设备的打开与释放打开设备是通过调用file_operations结构中的函数open( )来完成的,它是驱动程序用来为今后的操作完成初始化准备工作的。

在大部分驱动程序中,open( )通常需要完成下列工作:1.检查设备相关错误,如设备尚未准备好等。

2.如果是第一次打开,则初始化硬件设备。

3.识别次设备号,如果有必要则更新读写操作的当前位置指针f_ops。

4.分配和填写要放在file->private_data里的数据结构。

5.使用计数增1。

释放设备是通过调用file_operations结构中的函数release( )来完成的,这个设备方法有时也被称为close( ),它的作用正好与open( )相反,通常要完成下列工作:1.使用计数减1。

2.释放在file->private_data中分配的内存。

3.如果使用计算为0,则关闭设备。

设备的读写操作字符设备的读写操作相对比较简单,直接使用函数read( )和write( )就可以了。

但如果是块设备的话,则需要调用函数block_read( )和block_write( )来进行数据读写,这两个函数将向设备请求表中增加读写请求,以便Linux内核可以对请求顺序进行优化。

由于是对内存缓冲区而不是直接对设备进行操作的,因此能很大程度上加快读写速度。

如果内存缓冲区中没有所要读入的数据,或者需要执行写操作将数据写入设备,那么就要执行真正的数据传输,这是通过调用数据结构blk_dev_struct中的函数request_fn( )来完成的。

设备的控制操作除了读写操作外,应用程序有时还需要对设备进行控制,这可以通过设备驱动程序中的函数ioctl( )来完成,ioctl 系统调用有下面的原型: int ioctl(int fd, unsigned long cmd, ...),第一个参数是文件描述符,第二个参数是具体的命令,一般使用宏定义来确定,第三个参数一般是传递给驱动中处理设备控制操作函数的参数。

ioctl( )的用法与具体设备密切关联,因此需要根据设备的实际情况进行具体分析。

设备的中断和轮询处理对于不支持中断的硬件设备,读写时需要轮流查询设备状态,以便决定是否继续进行数据传输。

相关文档
最新文档