LINUX下USB视频设备用户空间驱动研究与开发

上传人:无*** 文档编号:79445568 上传时间:2022-04-23 格式:DOC 页数:93 大小:1.09MB
收藏 版权申诉 举报 下载
LINUX下USB视频设备用户空间驱动研究与开发_第1页
第1页 / 共93页
LINUX下USB视频设备用户空间驱动研究与开发_第2页
第2页 / 共93页
LINUX下USB视频设备用户空间驱动研究与开发_第3页
第3页 / 共93页
资源描述:

《LINUX下USB视频设备用户空间驱动研究与开发》由会员分享,可在线阅读,更多相关《LINUX下USB视频设备用户空间驱动研究与开发(93页珍藏版)》请在装配图网上搜索。

1、浙江大学硕士学位论文图目录浙江大学计算机科学与技术学院硕士学位论文 Linux下USB视频设备用户空间驱动研究与开发 姓名:徐家 申请学位级别:硕士 专业:计算机应用技术 指导教师:陈奇20100308摘要Linux设备驱动一般运行在内核空间,近些年来,为了提高驱动开发效率, 一些研究人员提出了在用户空间下开发驱动的概念,相对于内核驱动,用户空间 下的驱动有着以下优点:1,调试的方便;2,用户空驱动出错不会引起系统崩 溃;3,用户空间驱动可以使用C语言库,简化驱动的开发;4,用户空间驱动对 内核依赖性较少,有更好的移植性,并且可以发布封闭源代码的驱动。应用程序可以通过系统调用和内核驱动进行交互

2、,但对于用户空间驱动,需 要实现相应的框架来支持应用程序与驱动之间的交互。本文针对视频设备的特 性,设计并实现了用户空间的V4L2交互框架,通过该框架,应用程序可以方便 的以V4L2标准与用户空间驱动进行交互,并能减少用户空间驱动的开发工作量。视频设备有较复杂的工作机制和数据格式,在用户空间下开发丨能够有效的 提高驱动开发效率和降低调试的难度。本文从USB视频设备的共性出发,利用 Libusb库设计并实现了 USB视频设备的用户空间驱动,并使用C+语言以面向对 象的思想来组织驱动的开发,并实现了视频驱动中可重用的传输缓冲区模块,同 时C+相对与C语言更强的语言安全性也提髙了驱动的稳定性。关键词

3、:Linux驱动,视频设备,用户空间,V4L2交互框架,传输缓冲区浙江大学硕士学位论文AbstractAbstractLinux device drivers usually run in kernel space. Recent years, in order to improve the driver development efficiency, some researchers propose the user space driver development concept. Compare to kernel space driver, user-space driver has

4、the following advantages: 1, convenience of debugging; 2,the user space driver error will not cause system crashes ; 3,the user space drivers can use the C language library, simplify driver development; 4, user-space drivers are less dependent on the kernel, so have better portability, and can relea

5、se closed source drivers.The application uses the system calls to communicate with kernel driver, while in user space driver, there needs an appropriate framework to facilitate the interaction between application and driver. In this paper, considering the characteristics of video equipment, it desig

6、ns and implements the user space V4L2 interaction framework. Using this framework, the application can communicate with user-space drivers under V4L2 standard easily, and also reduces the workload of the user space driver development.Video device has complex working mechanisms and data formats, deve

7、lop its driver in user space and improve the develop efficiency and reduce debugging difficulty. This article uses Libusb library to design and implement a user space USB video device driver, and uses the C + +, with object-oriented idea to the organize driver development, and realizes a reused tran

8、smission buffer module. C+ s more safety in language can increase the driver stability.Keywords : Linux driver, video device, user space, VL42 interaction framework, transfer bufferiii浙江大学硕士学位论文图目录图目录2.1应用程序与内核驱动交互方式72.2应用程序与用户空间驱动交互方式83.1 V4L2交互框架结构图144.1 USB设备的配置、接口与端点关系图244.2 USB视频设备拓扑结构254. 3典型U

9、SB视频设备的接口描述符264. 4驱动整体模块示意图304. 5视频帧状态转换图334. 6视频队列操作示意图345.1等时传输函数调用流程405. 2视频帧填充过程415. 3数据读写同步方法445.4视频数据传输流程45图图图图图图图图图图图图图图5.5传输缓冲区对象UML图46浙江大学硕士学位论文Abstract表目录1查询以及初始化设备V4L2命令.2数据传输V4L2命令3 V4L2交互框架上层接口1批量传输端点和等时传输端点比较1 USB命令格式2 BFH字段构成1获取视频帧时间对比33345566 表表表表表表表表12 20 27 38 40 49 492 Luvcview资源使

10、用对比vii浙江大学硕士学位论文第1章绪论致谢转眼间,两年半的研究生生涯快要结束了,在这里要感谢所有帮助我的老师 和同学。首先,我要感谢我的导师陈奇老师,陈老师严谨的治学态度和平易近人 的为人处世给我留下了深刻印象,也将使我终身受益。陈老师在科研上对我不断 的指导和鞭策是我不断成长的动力,同时陈老师在生活和学业上给了我各方面的 关怀,使我能够顺利的完成毕业设计。其次,我要感谢何江峰师兄,无论遇到科研还是生活上的问题,他都能乐于 帮助并,并耐心解决。接着我要感谢王志鹏、宋国兵同学正是与他们一起合作,才顺利的完成了实 验室与华为预研部和合作的项目。同时也要.感谢夏杰、程春惠、车延辙、钱丰等 同学,

11、正是这些同学组成了实验室一个团结的集体。最后我要感谢我的父母亲及其他关爱的人,我的成长和进步里不开你们的支徐家2010年1月于求是园第1章绪论1.1课题研究背景设备驱动是硬件与应用程序之间的桥梁,也是Linux系统中不可缺少的一部 分。从Linux 1.0到2. 6版本的发展过程中,Linux内核对硬件设备的支持越来 越全面,同时随着硬件设备种类、型号的不断增加,Linux内核中的驱动程序的 代码总量也在不断增加,已占到内核代码的70%左右。研究表明设备驱动问题 是影响操作系统稳定性的主要因素之一23】,而Linux内核中驱动代码中的错误是 其他内核代码的7倍左右24】。随着计算机硬件性能的不

12、断提高,设备驱动效率不 再成为制约硬件设备性能表现的瓶颈,而驱动的稳定性的越来越受到重视。同时, 硬件设备的更新换代和新设备出现的速度也越来越快,对于硬件驱动的开发时间 周期也要求越来越高21】。传统的Linux设备驱动一般由C语言开发,而C语言缺 乏类型安全性是影响Linux设备驱动稳定性的重要因素之一。相对于应用程序, Linux设备驱动在开发方法和工具上所取得进展也相当有限,缺乏相关的开发 SDK和开发工具,驱动幵发往往需要开发人员精通内核底层的数据结构,不仅有 着较高的门槛,同时也不利于缩短驱动开发周期。1.2国内外研究现状分析针对Linux设备驱动的稳定性和开发效率问题,国内外的一些

13、学者进行了相 关的研究,研究领域主要集中在以下几个方向:1,在Linux内核中引入JAVA 等类型安全语言进行驱动开发;2,通过髙层的建模语言对驱动进行开发;3用 户空间驱动开发的相关技术研究。Shan Chen, Lingling Zhou23提出了在Linux内核中使用java语言进行驱动 开发的方法。Shan Chen, Lingling Zhou在实现内核空间Java虚拟机基础上, 给出了基于内核Java虚拟机的驱动开发方法,在驱动中引入Java虚拟机能够从 编译、运行时提高驱动的稳定性,当然在驱动执行效率上可能会有所降低。浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现Fa

14、brice Mrillon, Laurent R6veilUre2U提出了使用接口定义语言 Devil 进行驱动开发的方法。Devil语言从I/O端口、寄存器和设备变量三个层次来对 驱动进行抽象,通过Devil语言能够清晰明确的表示驱动涉及到的端口、寄存器 和设备变量,以及三者之间的相互联系。Devil程序编译后生成的相应C语言 宏,驱动程序需要操作硬件时直接调用这些C语言宏,这样既能够避免直接编写 对硬件操作的代码而带来的错误,并能够使开发人员在一个更高的语言层次开发 驱动,提高驱动开发的效率。Christopher L. Conway, Stephen A. Edwards125提出 了通

15、过 Domain-Specific Language-NDL语言开发驱动的方法,NDL借鉴了 Devil语言的语法结构。NDL驱 动的描述由寄存器集合、访问寄存器的协议和一系列设备函数构成。NDL语言通 过对驱动中常用的写寄存器、I/O数据拷贝命令进行了抽象和封装,使得需要多 行C语言代码实现的操作在NDL中可以简洁的被表示,同时NDL将设备相关的系 统调用或执行代码封装为库函数,方便开发人员的使用。目前大多数设备驱动开发方法的研究都在Linux内核空间中展幵,但Linux 内核空间编程相对与用户空间编程来说限制较多,使用一些的新的方法或非传统 的手段往往需要对内核进行重新改造,工程量较大。用

16、户空间驱动作为一个新兴 的概念,则有着如下优点:1,驱动调试的方便,用户用GDB等常用工具即可进 行驱动的调试;2,驱动开发的便利,在用户空间开发驱动时,可以使用C语言 库,并使用第三方的开发库,提高驱动的开发效率;3,用户空间驱动挂起了, 可以被简单杀死并重启动,并不会影响整个系统的运行3】;4,有学者提出在内 核使用C+面向对象的思想来组织驱动,提高驱动的重用性4】,在用户空间,由 于不受内核对C+语言的限制,可以用更方便的通过面向对象的思想来实现驱动 程序,提高同类型驱动代码的重用性;5,在驱动内部可以实现一些复杂的功能, 如音视频数据的压缩等。因此在用户空间中,开发驱动程序不仅有着较大

17、灵活性, 并且能够提高驱动程序的健壮性和开发效率。1.3用户空间驱动分析Linux地址空间可以分为内核空间和用户空间,应用程序主要运行在用户空 间,而系统服务、驱动程序等一般运行在内核空间,运行在内核空间的程序优先 级较高,并能使用特权级别的操作,有较高的执行效率,但内核空间程序的问题 可能会导致系统崩溃。内核空间中只支持C语言编程,无法直接使用较高层的语 言如C+、Java等进行开发,在内核空间中无法使用C语言库或其他开发库,一 般只能使用内核数据结构和系统函数,同时也不支持浮点数操作,内核空间程序 的这些限制直接了制约了驱动程序的开发速度,同时不利于提高驱动的稳定性。 User Space

18、 I/O System,简称UIO,是作为Linux内核中对用户空间驱动开 发提供支持的一个框架在Linux2. 6. 23版本中被加正式入内核。UI0并不是一个 广义上的驱动框架,在Linux内核中被支持的很好的驱动子系统,如串口和USB 等子系统,并不在UI0支持的范围之列。UI0支持的设备需要满足如下特性:1, 设备内存可以被映射,并且通过写设备I/O内存可以直接操控硬件;2,设备通 常能够产生中断信号;3,设备并不在标准的Linux设备子系统支持之列【5。UI0 可以将驱动大部分的工作都放在用户空间,但在内核空间还是需要编写小部分代 码,这部分代码主要是工作是将驱动连接到总线,并注册中

19、断处理程序,使得用 户空间驱动能接收到硬件中断。用户空间的驱动进行注册后,会生成/dev/uioO 的设备文件,应用程序能够以的open、ioctl等常规指令对该设备文件进行操作。 据估计,在内核空间实现68个标准的ioctl指令的驱动程序需要5000行左右的 代码,但在用户空间实现同样功能的驱动程序,只需要3000行用户空间代码和 156行内核空间代码。但UI0作为一个刚刚发展起来的框架,功能还比较有限, 目前只支持字符型设备驱动,而不支持块设备、网络设备等驱动,对其他Linux 设备子系统支持也不是很好。Libusb是支持用户空间下访问USB设备的函数库。Linux下最初只能在内核 空间中

20、访问USB设备,但Linux内核开发人员看到了在用户空间下访问USB设备 的必要性,因此在Linux中引入了 usbdevfs文件系统。usbdevfs和proc 样, 并不是一个实际的文件系统,而是在内存中动态生成的虚拟文件系统,通过 usbdevfs及其提供的函数接口,在用户空间能够直接访问USB设备,也使得在 用户空间开发USB设备驱动成为可能。为了避免与原有的devfs文件系统产生混 淆,usbdevfs 在 Linux2. 6 内核中被更名为 usbfs。usbfs 加载在/proc/bus/usb 目录下,该目录下的每一个设备文件对应了一个实际USB设备,usbfs定义了 相关的函

21、数和数据结构,通过引用相关头文件,便可以在用户空间程序中访问 usb设备。Libusb实际上是通过usbfs来访问USB设备6】,不过对相关usbfs 函数接口进行了封装,是一个更高层的函数库。Libusb有良好的跨平台特性, 可以运行在Linux、FreeBSD、NetBSD、MacOs x、Windows等平台,因此基于 Libusb开发的USB视频设备驱动、USB存储设备驱动或其他USB外设驱动也有良 好的移植性。5浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现VGALIB是Linux下一个底层的图形库,功能类似与X Windows,应用程序通 过VGALIB提供的API,可

22、以直接操作VGA的端口。VGALIB为进程分配了和视频 内存区域同样大小的内存,并支持进程能够直接访问视频内存来控制屏幕显示Linux用户空间驱动作为一个起步不是很久的事物,也存在着一些不足, 虽然一些现有的技术能够使得在用户空间直接访问硬件设备成为可能,但相对于 内核空间驱动,主要还存在以下不足之处:1,用户空间驱动还未形成类似内核 驱动一样形成完善的框架,包括应用程序如何调用空间驱动,应用程序和驱动之 间的消息和数据交互的机制。2,用户空间驱动与应用程序的藕合性问题,现有 的交互方式下,用户空间驱动与应用程序往往会高度藕合,不符合软件设计中高 内聚低藕合的要求9】;3,用户空间驱动的效率问

23、题,相对于内核驱动,用户空 间驱动在效率上可能会有所降低。4,一些内核驱动中的标准协议,如V4L2等, 需要在用户空间驱动中实现。1.4本文的工作与创新本文分析了用户空间与内核空间中驱动开发在实现机制和具体细节上的差 异,针对用户空间驱动现有的不足,设计并实现了 V4L2交互框架,该交互框架 有良好的重用性和扩展性,方便应用程序和视频设备用户空间驱动之间的交互, 同时能够对用户空间下视频设备驱动开发提供有效的支持,降低驱动开发的工作 量。并利用Libusb库提出并实现了 USB视频设备用户空间驱动幵发方法,该方 法能够有效提高USB视频设备驱动开发的效率。并在用户空间驱动开发中使用 C+语言面

24、向对象的思想来组织驱动的开发与设计,实现了可重用的传输缓冲区 模块,并使驱动的代码有着良好的维护性和扩展性,并提高了驱动程序的健壮性。 本文对以下几方面内容进行了研究-浙江大学硕十学位论文第2章用户空间驱动和内核驱动比较分析对比了 Linux内核驱动和用户空间驱动在程序特性、框架支持、调 试方法、可移植性方面的差别,并指出了用户空间驱动需要改进的地方。 对于用户空间驱动与内核空间驱动在调用接口上的不同,提出并实现了 V4L2交互框架,该框架有效的屏蔽和解决了调用接口的问题,并提供了 应用程序与用户空间视频设备驱动之间的控制传递,数据传输的相应机 制,并实现了框架的标准调用接口,通过该框架,可以

25、减少用户空间驱 动开发的复杂度。分析了 USB视频设备的相关协议与标准,讨论了对USB视频设备进行控制的基本原理和方法。 分析了用户空间下对USB设备进行读写访问的Libusb库,并在此基础上 提出了 USB视频设备驱动在用户空间的实现的方法,针对用户空间驱动 与内核空间驱动的不同,分析并给出了在用户空间实现USB视频设备驱 动的实现方法,并重点讨论了驱动传输缓冲区的实现机制与同步策略。 对用户空间驱动和内核驱动进行了相应的测试,分析对比了两者在驱动 性能,传输效率、CPU占用率等方面的差别。1.5本文内容组织结构第2章对Linux用户空间驱动和用户空间驱动在程序特性、框架支持、调试 方法和移

26、植性方面做了对比,分析了两种形式的驱动各自的优缺点,并指出了用 户空间驱动需要改进的方面。第3章对Linux下的视频标准V4L2做了分析和阐述,并针对用户空间视频 驱动,提出了针对支持用户空间驱动的V4L2交互框架,并阐述了该框架的工作 机制和实现原理与方法,以及提供的相应的接口。第4章分析了 Linux下访问USB设备的开源库Libusb的原理和使用方法, 以及使用Libusb进行驱动幵发的优点,并提出了在用户空间下通过Libusb库开 发USB视频设备驱动的方案,并给出了驱动的详细设计。第5章分析了内核驱动和用户空间驱动的实现在具体技术细节上区别,结 合C+面向的对象思想,给出了 USB视

27、频设备用户空间驱动的实现,并重点分析 了驱动传输缓冲区的并发访问以及加锁机制,并实现了一个可重用的驱动传输缓 冲区模块。第6章针对USB摄像头,通过对Luvcview播放器的改造,对USB视频设备 用户空间驱动进行了测试,并和内核空间驱动在性能进行了比较。第7章对本文的工作进行了总结,以及对需要改进的地方进行了展望。第2章用户空间驱动和内核驱动比较 2.1程序特性用户空间驱动和内核驱动在程序特性有比较大的差别,用户空间驱动属于用 户空间编程,而内核驱动属于内核编程的范畴,两者在使用到的头文件、函数、 数据结构等都有比较大的差别,程序的特权级别与优先级也不同,下面阐述了两 者在程序基本特性上的差

28、别。2.1.1内核空间驱动程序特性Linux的内核结构继承了 Unix的单内核结构,整个内核作为一个大的单的进 程运行。运行在内核的驱动程序可以分为两大类,一种是被直接编译进内核,随 着内核的启动而被加载;另一类是作为模块而被动态加载,两种驱动虽然加载方 式不同,但一旦运行起来,内核便无差别对待它们。作为模块加载的驱动由 module_init函数作为加载入口,由moduleexit函数作为卸载的出口。内核驱 动虽然是由C语言开发,但在内核驱动中,无法使用C语言库,如printf、roalloc 等函数,而必须使用相应的系统调用或内核函数来替代,如printk、kmalloc等。 从效率上来说

29、,系统调用优于C语言库,因为用户空间C语言库函数执行时一般 展开为若干个系统调用。内核驱动或是内核线程的栈空间一般只有8K,该8K栈 空间还会被线程引起的中断程序共享使用,因此内核程序能使用的栈空间是相当 有限的,所以在内核驱动中需要避免使用大的结构体或递归操作,否则容易导致 驱动程序出错。内核驱动在编译时会依赖于Linux内核的源代码,运行时则依赖 于内核的其他模块,而Linux各个版本之间都会发生源代码的变化,内核驱动代 码也需要进行修改才能适应不同版本的源代码,因此,内核驱动在可移植性上一 般都不是很好。并且运行在内核空间的程序往往需要应付更多的并发操作,这些 并发操作可能来源多个进程对

30、驱动的访问或是中断的异步运行等【3】2.1.2用户空间驱动程序特性7浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现用户空间驱动属于用户空间程序的范畴,基本特性与其他的用户空间进程类 似。程序的优先级一般默认为20,并且无法进行修改。而在内核中,线程不但 能够设置优先级值,甚至将自己设为实时。同时用户空间驱动无法使用一些内核 中才有的特权操作,如关闭系统中断等,这也避免了用户空间驱动产生致命的错 误。从理论上讲,用户空间驱动的在执行效率上一般没有内核驱动高,尽管如此, 现在还是有一些用户空间驱动被广泛使用,如Linux下的X服务器,随着CPU运 行速度和内存性能的不断提高,效率己经不

31、是一个瓶颈,用户对驱动程序稳定性 和开发者对驱动程序研发速度和质量的需求会成为开发驱动时考虑的一个重要 因素4,当然开发用户空间驱动时,也需要借鉴内核中一些高效的程序架构。对 于一些要求实时性高,频繁需要中断响应的驱动,应该还是放在内核中运行,但 对于许多设备,在用户空间驱动并不会影响其实际性能,如USB视频设备、显示 设备等。由于用户空间驱动不会直接依赖与内核代码和内核模块,相对于内核模 块,有着较好的移植性,驱动开发人员可以直接发布可执行程序,而不必发布源 代码。2. 2框架支持对于Linux内核驱动,Linux的设备模型和系统调用可以减少驱动开发者的 实际工作,当应用程序使用系统调用来向

32、硬件发送控制命令时,Linux内核提供 的消息转发机制会自动将控制命令发送到对应的内核模块,并通过系统函数,完 成应用程序和驱动程序的之间的数据拷贝,而设备模型可以自动为驱动处理一些 事务,如热插拔、引用计数等。应用程序与内核驱动的调用关系如图2.1。应用程序用户空间系统调用接口内存管理 进程管理 虚拟文件系统T 系统空间 设备驱动图2.1应用程序与内核驱动交互方式浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现用户空间驱动作为一个起步不久的事物,框架层面的支持比较少,开发 人员可能要自行处理应用程序和驱动之间的消息命令的发送,和一些驱动与 应用程序之间标准的实现,不过相应的框架一旦

33、实现,就可以被同类设备驱 动重用,简化驱动的开发。应用程序与用户空间驱动的关系如图2.2。交互框架.内核空间图2.2应用程序与用户空间驱动交互方式2. 2.1 Linux设备模型Linux设备模型直接支持着内核驱动的开发,Linux设备在内核中都有一个 共同的祖先kobject。kobject作为一个最原始和底层的内核对象,经过层层嵌 套后被实际设备对象引用。Linux中一个硬件不论其实际功能是什么,在Linux 设备模型中,一般需要满足以下几个功能:引用计数、在sys目录中被表示、热 插拔事件处理等。在编写驱动程序时,开发人员不需要去处理这些细节,正是 kobject完成了这些事情。kobj

34、ect结构中有几个比较重要的数据结构,分别是: 1,struct kref kerf表示该kobject对象的引用计数,当该kobject被创建时, 引用计数为1,通过get和put操作可以增加或减少该kobject的引用计数,当 引用计数为0时,该kobject被释放;2, struct kobject * parent,指向其 父kobject的指针,父kobject表示拥有该kobject设备的上一层次设备,对于 一个usb设备来说,其父kobject表示的设备可能是一个hub, parent指针的主 要作用是在sysfs目录中层级结构的表示;3, struct kset * kset,

35、包含该 kobject对象的kset指针。w个kobject对象由kobject_init函数创建,不 过单纯创建一个kobject对象是没有实际意义的,一般需要设置其从属的kset, 并通过kobject_add函数来设置其父kobject,这样通过层层关联,一个kobject 才能和实际设备结合发挥其作用。9浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现Kset中包含了一组kobject对象的集合,kset类似于一个容器类对象,其 中包含相关联的kobject对象集合。Kset中所有的kobject被组织成一个双向 链表,被包含的kobject可能被内嵌于其他的对象中。Kset

36、的初始化等函数也类 似于kobject,可以遍历kset来枚举所有的关联设备,如所有的PCI设备等。Subsystem描述了系统中某一类子系统,如块设备子系统,一个设备子系统 结构中包含了一个kset对象和rw_semaphore对象,每一个kset必须属于某个 subsystem, 而rw_semaphore信号量则提供了对subsystem中kset对象的互斥 访问。由于subsystem只是简单的对kset的封装,在Linux2. 6. 21版本之后, subsystem已被kset所取代。一个设备在驱动程序中可能以usb_device、pci.dev等具体设备的结构来表 示,但在底层,

37、一个设备通常以struct device结构来表示。struct device中 比较重要的数据结构有:1,struct device *parent,表示该设备依附的父设 备;2,struct kobject kobj,代表内嵌于该设备的 kobject 对象;3 , char busid 和struct bustype *bus用来表示挂载该设备的总线;struct device_driver *driver表示该设备的驱动。struct device结构一般被内嵌更在高层的设备结 构中,如USB设备结构usb_device,视频设备结构video_device等。2. 3驱动调试方法在驱

38、动调试方法上,内核驱动和用户空间驱动的差异比较大,用户空间驱动 的调试可以用常见的GDB调试,也可以在其他C/C+ IDE中调试。但内核驱动的调试复杂的多,一般有以下几种方法:printk函数,printk 将内核信息打印到内核信息缓冲区,在用户空间可以通过dmesg命令来查看驱动 打印信息,但该方法调试效率偏低,并且打印数据过多的话,后打印的信息会覆 盖较早打印的信。kdb, kdb只能对内核驱动进行汇编语言级的调试,对于调试复杂的驱动来说 调试过程不是很直观。kcore,kcore配合gdb可以将整个内核当作一个应用程序来调试,不过在这 种方式下,无法设置断点调试或单步执行,调试功能比较有

39、限。kgdb, kgdb可以对内核驱动进行源代码级的调试,kgdb需要两台机器进行 调试,一台作为目标机运行被调试的内核,另一台作为主机通过串口连接到目标9机进行调试31,对于可加载模块的调试,需要先捕获模块的symbol信息,但调 试过程中往往无法捕获实际运行过程中由于一些异步事件引发的错误,kgdb的 调试方法是所有内核调试方法中功能最强大的,但使用起来也是最复杂的。2. 4驱动可移植性影响内核驱动移植性的主要因素为内核驱动对Linux源代码和内核版本的依 赖性,和不同平台在基本数据结构上的差异,LinuX2. 4到Linux 2. 6在源代码 有了很多的变化,甚至在内核模块的编译方式都有

40、差别,Linux 2. 6的各个子版 本之间的源代码也又差异,内核驱动在不同版本的Linux内核之间移植可能会遇 到需要修改驱动源代码的情况。用户空间驱动的开发不会直接依赖于内核的源代码,更多依赖的是Linux内 核向用户空间提供的系统调用和函数调用,相对于源代码来说,这些系统调用和 函数调用接口比较固定,即使在函数实现上发生改变,但在调用接口、参数类型 上一般是不会变化的,因此用户空间驱动的移植相对比较方便。2. 5本章小结本章重点比较了 Linux内核驱动和用户空间驱动在程序特性、框架支持、调 试方法和移植性方面的差别,同时也分析了内核驱动和用户空间驱动各自的优缺第3章V4L2交互框架的设

41、计与实现3.1 Linux视频V4L2标准Video for Linux 2,简称为V4L2,是Linux下的视频驱动的标准框架,在 前身V4L的基础上发展起来。V4L2支持的设备几乎涵盖了 Linux下所有的视频 设备,包括摄像头、数字电视设备、模拟电视设备、视频输出设备等等。作为一 个标准框架,V4L2有两层含义,首先对于应用程序,应用程序可以按照V4L2定 义的操作命令,进行打开视频设备、获取视频设备信息、传输视频数据、设置视 频属性等等操作;对于驱动,必须相应的实现V4L2定义的一系列回调函数,与 应用程序的调用相对应,当然并不是V4L2定义的所有回调函数驱动都要实现, 驱动可以根据设

42、备的特性,实现V4L2定义操作的一个子集,但和视频数据传输 相关的操作一般是必须实现的。V4L2中应用程序的工作流程如下:首先通过open系统调用打开视频设备, 接着通过ioctl系统调用发送V4L2命令来查询视频设备基本信息,并初始化视 频设备参数。主要的查询设备信息及初始化设备的V4L2命令如表3.114。表3.1査询以及初始化设备V4L2命令V4L2命令命令作用VIDIOC_QUERYCAP查询视频设备功能VIDIOCSFMT设置视频帧格式属性(高度、宽度、像素格式)VIDIOCSPARA设置视频传输参数(视频帧传输间隔)当应用程序成功执行上述查询和初始化命令后,可以开始视频数据的传输了

43、。V4L2中,视频数据的传输一般不通过read、write系统调用来进行,而是采取内存映射的流传输方式,流传输方式不要实际数据的拷贝,驱动和应用程序之间只需要交换被映射内存的指针。具体做法如下:应用程序首先通过ioctl系统调用发送VIDIOC_REQBUFS命令来申请传输缓冲区,申请到传输缓冲区位于驱动程序内,应用程序接着通过调用ioctl发送VIDIOC_QUERYBUF命令来查询申请到的传输缓冲区的具体信息,并通过mmap系统调用将传输缓冲区映射到应用程序的11浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现地址空间,驱动和应用程序之间的数据传输,只需通过读写被映射的传输缓冲区

44、。 然后应用程序发送VIDIOC_STREAMON命令,通知驱动开始数据传输。应用程序获 取一个视频帧,需通过发送VIDIOC_QBUF命令将一个v412_buffer放入传输缓冲 区进行传输,然后通过发送VIDIOC_DQBUF命令获得完成传输的vMSJmffer。 应用程序通过不断的发送VIDIOC_QBUF和VIDIOC_DQBU命令,便能持续的从视频 设备获得视频数据。最后,当应用程序退出时,通过发送VIDIOC_STREAMOFF命 令来结束传输。视频数据传输相关的V4L2命令如表3. 2。表3.2数据传输V4L2命令V4L2命令命令作用VIDIOC_STREAMON幵启视频数据的流

45、传输VIDIOC_STREAMOFF关闭视频数据的流传输VIDIOC_REQBUFS申请传输缓冲区VIDIOC_QUERYBUFS查询传输缓冲区VIDIOC_QBUF将空的视频帧放入传输缓冲区VIDIOC_DQBUF将填充过的的视频帧从传输缓冲区取出当视频数据传输开始后,应用程序还可以对视频的显示属性进行进一步的操 作,如亮度、对比度、伽玛值等等,这部分操作通过发送VIDIOC_S_CTRL命令来 完成。应用程序中通过ioctl系统调用发送的V4L2命令最终会发送到驱动,驱动执 行相应命令后将执行结果返回给应用程序。通过ioctl系统调用发送的命令,在 驱动中的入口一般为驱动中的ioctl回调

46、函数,ioctl回调函数中负责将该命令 附带的参数数据拷贝到驱动空间内并根据命令执行对应的代码。V4L2中的另一个特点是其数据传输的方式,V412_buffer代表一个视频帧, 驱动中可以使用v412_buffer队列来管理传输缓冲区,应用程序读数据是从 v412_buffer队列中取出一个视频帧,使用完后将视频帧再次入队,进行重新填 充,如此循环来获取数据。3. 2 V4L2交互框架的必要性在内核驱动中,应用程序和驱动程序的交互可以通过基本的read、write, 更复杂的交互可以通过ioctl命令。无论是read、write还是ioctl命令,都是 Linux的标准系统调用,也就是说,驱动

47、程序和应用程序不需要关心read、write 和ioctl是如何从用户空间经过复杂调用和转换,最终将指令发送到对应的内核 模块。应用程序只需要使用这些函数,而驱动程序只需要负责对接收到的read、 write,和ioctl等命令进行处理,Linux内核负责了应用程序和驱动程序之间 的消息和数据转发。系统调用的实质是内核空间向用户空间提供的一种接口,用户进程可以通过 read、write等系统调用来访问设备文件17,执行系统调用时,会在用户态和内 核态之间发生切换。在编写用户空间驱动程序时,驱动和应用程序都工作在用户 空间,无法直接使用系统调用来实;现消息和数据的转发,因此需要有一种新的框 架来

48、支持用户空间驱动和应用程序之间的消息数据传递,并且需要特定的驱动标 准,对于用户空间的视频设备驱动,本文提出的V4L2交互框架正是起到了相应 作用。3. 3 V4L2交互框架整体架构V4L2交互框架有以下特点:首先,该交互框架有着良好的通用性,支持所有 符合V4L2标准的视频设备驱动,同时,该框架还有着良好的扩展性,进行扩展 后,对可以支持其他类型设备的用户空间驱动;其次,该交互框架实现了相应 的open、close、ramap、ioctl等原有系统调用的基本功能,并提供了类似的调 用接口,使的原有的应用程序仍可以只需修改极少源代码的情况下实现对用户空 间驱动的访问和使用,用户空间驱动程序则仍

49、可以保留内核驱动对open、close、 ioctl命令传统的处理方式;最后,该框架充分借鉴和利用了 Linux内核中的消 息传递机制,有较高的执行效率,框架结构如图3.1。17应用柠序层返冋数据tnn控制命令 V4L2交互框架上层.VI.、互架 交框 V4L2交互框架K层回S行果 返笛执结_ NmwR调! 函数O 驱动程序层 m 3. 1 V4L2交互框架结构图如图3. 1所示,V4L2交互框架可以分为两层,上层主要负责接受和解析应用 程序的控制命令,井将其转换成V4L2交互框架的消息格式发送到交互框架下层。 下层根据接收到的框架消息,进行解祈,并调用驱动程序相应的回调函数进行处 理。交互框

50、架并不是一个独立运行的进程,框架上层运行在应用程序的地址空间 内,而框架下层运行在驱动程序的地址空间内,因此有着较低的开销。V4L2交 互框架上层和下层之间通过netlink发送消息命令。netlink是Linux中用户空 间和内核空间通信的基本方法Linux内核中的消息传递和转发机制基本都是 基十netlink实现的,如ioctl系统调用的消息发送等,不过Netlink同样可 以在用户进程间通信间使用,netlink把进程PID作为通信地址,更加方便了进 程间的消息传递。交互框架最大程度1:屏蔽了用户空间驱动和内核空间驱动调用接口上的差 异,并有良好的通用性和扩展性。用户空间的驱动程序不需要

51、关心与应用程序的 消息数据的与控制命令的传递问题,应用程序也可以通过与原系统调用类似的接 口來对用户空间驱动程序进行调用。3.4V4L2交互框架实现内核驱动中,Linux内核自动完成了应用程序和驱动程序之间的消息命令传 递、接口调用的标准化,因此在开发内核驱动时,只需要按照一定的步骤调用系 统函数进行设备和驱动的注册,当应用程序使用某个系统调用访问设备时,Linux 内核中相应的机制进行应用程序和驱动之间的消息传递,内核空间和用户空间之 间的数据拷贝。对于视频设备用户空间驱动,交互框架需要实现以下的功能:1, 设备文件的生成,在内核驱动中,使用相应的设备注册函数后,便会生成对应的 设备文件,如

52、/dev/videoO,应用程序通过open该设备文件,便可以和驱动进行 交互,在用户空间驱动中,也需要实现设备文件的生成;2,控制命令的传递, 当应用程序发送ioctl、open、close、等命令时,需要完成驱动与应用程序之 间的消息数据的传递与拷贝;3驱动与应用程序之间内存的映射,对于视频设备 驱动一般通过共享内存来传输数据,因此交互框架需要完成驱动和应用程序之间 的内存映射。3. 4.1基于netlink的消息传递机制netlink在Linux中被广泛用于用户空间和内核之间的消息传递,Linux2. 4版 本后的内核中,几乎全部的中断过程与用户态进程的通信都是使用netlink实现 的

53、20。相对于其他IPC通信手段,netlink是一种全双工异步的通信方式26,更适 合于复杂的消息数据传递和处理,并且netlink支持组播的消息传递方式,更是其 他通信手段不可比拟的。netlink在本质上是一种基于socket的通信方式,但相 对于传统的socket, netlink通信地址不是IP和端口号,而是以进程PID作为通信 地址,这为进程间的消息传递提供了很大的便利。当用户空间进程和内核通信时, 内核被看作一个大的进程,PID为0。当用户空间进程互相通信时,PID就为各自 的进程ID,通过getpidO函数可以获得进程自身的PID。netlink的初始化函数如下:socket (

54、PF_NETLINK, socket_type, netlink一family),sokcet_type可以为S0CK_RAW和S0CK_DGRAM, netlink_family 表示了通信协议,对于用户空间驱动和应用程序之间的消息传递,通信的双方必 须有相同的协议,netlink规定了一系列的标准协议,有NETLINK_ROUTE、 NETLINK_R0UTE6、NETLINK_ARPD、NETLINK_FIREWALL等等,不同的协议对应着不浙江大学硕上学位论文第3章V4L2交互框架的实现同用途,如NETLINK_ROUTE被用来修改、获取设备信息,而NETLINK_ARPD用于维 护a

55、rp表信息。为了不和netlink所规定的标准协议发生冲突,在交互框架中,新 定义了一个协议NETLINKJJSRDIVER用于框架中的通信,netlink_faraily实质上 是一个整型值,具体做法如下#define NETLINKJJSRDIVER 22V4L2交互框架中有两个netlink对象,分别位于框架上层和下层,两个 netlink对象负责驱动和应用程序之间的框架消息发送。netlink中的struct nlmsghdr表示了一个消息头,结构如下:struct nlmsghdr u32 nlmsg_len; ul6 nlmsg_type; ul6 nlmsg_flags; u32

56、 nlmsg_seq;u32 nlmsgjid; nlmsg_len表示了该消息头的所附带的数据区的长度(包括消息头的长度), nlmsg_pid表示了消息发送者的进程PID, NLMSG_DATA(nlh)宏则返回了消息头的 实际数据区域。因此,发送一个消息,至少需要设置nlmsg_len、nlrasg_pid、 、NLMSG_DATA(nlh)三个字段的值。除了 struct nlmsghdr ,发送消息还需要设 置struct iovec和struct msghdr两个结构,struct iovec结构支持将多个 消息放入该结构,通过一次调用送多个消息,struct msghdr表示了发

57、送的消息 结构整体,包括了消息内容和发送目的地地址,设置完后通过sendmsg函数将消 息发送。netlink相对与传统的socket,不存在客户端和服务器端的概念,通信的双 方可以主动发起通信,也可以被动的接收信息,因此在框架运行时,既可以由应 用程序通过上层的netlink对象主动向驱动发送消息命令,当驱动中发生特定事 件时,驱动也可以通过下层的netlink对象主动通知应用程序。3.4. 2设备文件生成在内核驱动中,可以通过register_device等函数在/dev目录下生成特定的16浙江大学硕士学位论文第5章USB视频设备用户空间驱动的实现设备文件,应用程序通过该设备文件来调用驱动

58、。在V4L2交互框架中,使用了 命名管道来实现设备文件的生成。管道在Linux中有匿名管道和命名管道两种,匿名管道只能在同一进程内使 用,而命名管道可以在进程间使用。Unix系统中还有流式管道,流式管道支持 全双工的通信,但Linux中的管道只支持半双工的通信。向管道写入数据会阻塞 直到管道另一端有进程读取该数据,Linux管道也支持非阻塞的读写,但非阻塞 的方式不能保证数据能够被正确读写。当用户空间驱动被加载时,交互框架会为该驱动在/tmp目录下生成一个命名 管道并向该管道写入驱动进程的PID,从应用程序的角度来看,该管道即为设备 文件。当应用程序调用框架接口打开该管道文件时,交互框架读取该

59、命名管道并 返回驱动的进程PID。当应用程序调用化丨山cmd, args)函数向驱动发送 控制命令时,文件操作符fd即为驱动进程PID。交互框架就将该ioctl函数及 其参数进行解析并转换成netlink消息,并根据参数fd中的来确定消息的接收 方的PID,从而来发送消息命令。使用命名管道来生成设备文件的另一个好处是对于多个应用程序访问的控 制,视频设备与其他设备不同,一般都有访问的唯一性,即同一时间只能有一个 应用程序能够使用视频设备。当有一个应用程序成功打开该设备文件后,其他应 用程序无法从该设备文件对应的管道中读到进程PID,即无法访问该驱动,当应 用程序释放对该驱动的使用后,框架将驱动

60、的PID重新写入该管道,这样该驱动 可以重新被其他应用程序所使用。3.4. 3关键数据结构交互框架上层为应用程序提供调用接口,下层主要负责驱动注册、设备文件 的生成、netlink守护线程的运行、进程间的数据拷贝等。其中主要的数据结构 如下:struct u_devicestruct u_fi1e_operations * file_operations; enum u_dev_type type; unsigned int pid; key_t shrakey;struct u_device表示了一个用户空间驱动,file_operations表示了该驱 动的操作函数集合,type表示了设备

61、类型pid表示了该驱动的进程PID, shrakey 表示驱动创建的共享内存的标志符。struct u_fileoperations的结构如下:struct u_fi1e_operations int (*open) (struct u_file*);int (*release)(struct u_file*);int (本ioctl)(struct u_file*, unsigned int, void *);int (*mmap) (void * addr, int len, int port, int flags, int fd, int offet); 该结构中的函数指针指向驱动中定义

62、的open、relese、ioctl, mmap等函数, 当交互框架下层收到框架的消息后,对消息进行解析后,就通过U_file_0Perati0nS 的函数指针来调用驱动的函数。在驱动程序中,向交互框架注册驱动的步骤如下: 首先初始化 struct u_file_operations f_ops 对象,并对其中的 open、release、 ioctld等函数指针进行赋值,然后初始化struct u_device device对象,并对 其中 file_operations、type、pid、shmkey 分另丨J赋值,最后通过 register_device(&device)向交互框架注册该

63、驱动。注册完驱动后,交互框架获 得了该驱动的所有的基本信息,能够根据实际的框架消息来调用该驱动。3. 4. 4消息封装对于视频驱动,应用程序使用的最多是的ioctl系统调用,ioctl原型如下:int ioctl(int fd, int cmd, void *args) 交互框架中封装了 u_ioctl函数来实现了 ioctl的功能,两者仅在函数名上有区别,参数个数和类型都一致。对于U_i0Ctl调用,需要封装在框架消息体 内的参数有两个,cmd和args, fd在交互框架内是被作为netlink的发送地址, 因此不需要封装在消息内。cmd参数表明了该调用的V4L2命令类型,如 VIDIOCS

64、_FMT、VIDIOCDQUEUE等,该参数为一整型变量,因此可以方便的以 四个字节将其封装在消息体内。args参数表示了该命令附带的参数的指针。在 内核驱动中,该指针参数作为long型变量直接传递给驱动,内核驱动可以调用 copy_from_user函数来把该指针的数据从用户空间拷贝到内核空间。但在用户 空间驱动,如果传送实际的指针,由于地址空间的不同,是无法进行进程间的指 针数据拷贝的。在用户空间驱动,需要传参数数据,而不是参数指针。在交互框架中以实际数据来传输该参数,需要把数据从参数指针中拷贝出来, args 参数可能的类型有很多,如 struct v412_capabilit、struct v412_format、 struct v412_buffer等等,但在u_ioctl函数内,参数指针类型都退化成了空 指针,显然无法从空指针中获得数据区域的实际大小,并且不同类型的args参数 结构和大小都不同,如何从空指针中拷贝到合适大小的数据,首先可以参考下 Linux内核代码中对ioctl参数拷贝的处理。内核驱动中的ioctl回调函数实际获得了一个指向参数的lo

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!