linux设备驱动程序开发课件

上传人:cl****1 文档编号:592497086 上传时间:2024-09-20 格式:PPT 页数:81 大小:774KB
返回 下载 相关 举报
linux设备驱动程序开发课件_第1页
第1页 / 共81页
linux设备驱动程序开发课件_第2页
第2页 / 共81页
linux设备驱动程序开发课件_第3页
第3页 / 共81页
linux设备驱动程序开发课件_第4页
第4页 / 共81页
linux设备驱动程序开发课件_第5页
第5页 / 共81页
点击查看更多>>
资源描述

《linux设备驱动程序开发课件》由会员分享,可在线阅读,更多相关《linux设备驱动程序开发课件(81页珍藏版)》请在金锄头文库上搜索。

1、1TMT H E A R C H I T E C T U R E F O R T H E D I G I T A L W O R L D第七章第七章 linux设备驱动程序开发设备驱动程序开发2TM2ARM及Thumb指令集7.1设备驱动概述设备驱动概述n n设备驱动可以理解为操作系统的一部分,对于一个特定的硬设备驱动可以理解为操作系统的一部分,对于一个特定的硬设备驱动可以理解为操作系统的一部分,对于一个特定的硬设备驱动可以理解为操作系统的一部分,对于一个特定的硬件设备来说,其对应的设备驱动程序是不同的。比如网卡、件设备来说,其对应的设备驱动程序是不同的。比如网卡、件设备来说,其对应的设备驱动

2、程序是不同的。比如网卡、件设备来说,其对应的设备驱动程序是不同的。比如网卡、声卡、键盘、鼠标、显卡等。声卡、键盘、鼠标、显卡等。声卡、键盘、鼠标、显卡等。声卡、键盘、鼠标、显卡等。n n对于操作系统来说,挂接的设备越多,所需要的设备驱动程对于操作系统来说,挂接的设备越多,所需要的设备驱动程对于操作系统来说,挂接的设备越多,所需要的设备驱动程对于操作系统来说,挂接的设备越多,所需要的设备驱动程序也越多。操作系统本身并没有对种类繁多的硬件设备提供序也越多。操作系统本身并没有对种类繁多的硬件设备提供序也越多。操作系统本身并没有对种类繁多的硬件设备提供序也越多。操作系统本身并没有对种类繁多的硬件设备提

3、供持久不变的持久不变的持久不变的持久不变的“ “设备驱动设备驱动设备驱动设备驱动” ”,也就是说操作系统在没有设备驱动也就是说操作系统在没有设备驱动也就是说操作系统在没有设备驱动也就是说操作系统在没有设备驱动程序支持下是无法正常支配硬件行为的。程序支持下是无法正常支配硬件行为的。程序支持下是无法正常支配硬件行为的。程序支持下是无法正常支配硬件行为的。n n这个时候就需要独立开发一套适合自己产品的设备驱动。正这个时候就需要独立开发一套适合自己产品的设备驱动。正这个时候就需要独立开发一套适合自己产品的设备驱动。正这个时候就需要独立开发一套适合自己产品的设备驱动。正是操作系统留下了是操作系统留下了是

4、操作系统留下了是操作系统留下了扩展设备驱动的接口扩展设备驱动的接口扩展设备驱动的接口扩展设备驱动的接口,才有了现在支持各,才有了现在支持各,才有了现在支持各,才有了现在支持各种应用场合的硬件设备的蓬勃发展。种应用场合的硬件设备的蓬勃发展。种应用场合的硬件设备的蓬勃发展。种应用场合的硬件设备的蓬勃发展。n n对于嵌入式开发,更没有通用的驱动程序可以便用。因此,对于嵌入式开发,更没有通用的驱动程序可以便用。因此,对于嵌入式开发,更没有通用的驱动程序可以便用。因此,对于嵌入式开发,更没有通用的驱动程序可以便用。因此,驱动程序开发是整个嵌入式系统设计过程中必不可少的一部驱动程序开发是整个嵌入式系统设计

5、过程中必不可少的一部驱动程序开发是整个嵌入式系统设计过程中必不可少的一部驱动程序开发是整个嵌入式系统设计过程中必不可少的一部分。分。分。分。3TM3ARM及Thumb指令集7.1设备驱动概述设备驱动概述n n7.1.17.1.1设备驱动程序功能设备驱动程序功能设备驱动程序功能设备驱动程序功能n n设备驱动程序是设备驱动程序是设备驱动程序是设备驱动程序是LinuxLinux内核的重要组成部分。像操作系统的内核的重要组成部分。像操作系统的内核的重要组成部分。像操作系统的内核的重要组成部分。像操作系统的其他部分一样,其他部分一样,其他部分一样,其他部分一样,驱动程序在一个高优先级的环境下工作驱动程序

6、在一个高优先级的环境下工作驱动程序在一个高优先级的环境下工作驱动程序在一个高优先级的环境下工作,如,如,如,如果发生错误则可能会引发严重的问题。设备驱动程序控制了果发生错误则可能会引发严重的问题。设备驱动程序控制了果发生错误则可能会引发严重的问题。设备驱动程序控制了果发生错误则可能会引发严重的问题。设备驱动程序控制了操作系统和硬件设备之间的交互操作系统和硬件设备之间的交互操作系统和硬件设备之间的交互操作系统和硬件设备之间的交互,完成以下功能:,完成以下功能:,完成以下功能:,完成以下功能:n n对设备对设备对设备对设备初始化初始化初始化初始化和和和和释放释放释放释放;n n 对对对对设设设设备

7、备备备进进进进行行行行管管管管理理理理,包包包包括括括括实实实实时时时时参参参参数数数数设设设设置置置置,以以以以及及及及提提提提供供供供对对对对设设设设备备备备的的的的操操操操作接口作接口作接口作接口;n n 读读读读取取取取应应应应用用用用程程程程序序序序传传传传送送送送给给给给设设设设备备备备文文文文件件件件的的的的数数数数据据据据或或或或者者者者回回回回送送送送应应应应用用用用程程程程序序序序请请请请求求求求的的的的数据数据数据数据;n n检测和处理设备出现的检测和处理设备出现的检测和处理设备出现的检测和处理设备出现的错误错误错误错误。4TM4ARM及Thumb指令集应用程序应用程序应

8、用程序应用程序硬件层硬件层硬件层硬件层驱动程序驱动程序驱动程序驱动程序文件系统文件系统文件系统文件系统整个设备管理子系统的结构如图整个设备管理子系统的结构如图7.1所示。所示。5TM5ARM及Thumb指令集7.1设备驱动概述设备驱动概述n n2 2LinuxLinux设备驱动程序接口设备驱动程序接口设备驱动程序接口设备驱动程序接口n n系统调用是操作系统内核与应用程序之间的接口,驱动程序系统调用是操作系统内核与应用程序之间的接口,驱动程序系统调用是操作系统内核与应用程序之间的接口,驱动程序系统调用是操作系统内核与应用程序之间的接口,驱动程序则是操作系统内核与机器硬件的接口。则是操作系统内核与

9、机器硬件的接口。则是操作系统内核与机器硬件的接口。则是操作系统内核与机器硬件的接口。设备驱动程序能够直设备驱动程序能够直设备驱动程序能够直设备驱动程序能够直接访问硬件的代码,必须为应用程序提供系统调用。接访问硬件的代码,必须为应用程序提供系统调用。接访问硬件的代码,必须为应用程序提供系统调用。接访问硬件的代码,必须为应用程序提供系统调用。以便应以便应以便应以便应用程序能访问设备。用程序能访问设备。用程序能访问设备。用程序能访问设备。n n在在在在LINUXLINUX中,主要有三种设备即:中,主要有三种设备即:中,主要有三种设备即:中,主要有三种设备即:字符设备字符设备字符设备字符设备. .块设

10、备和网络块设备和网络块设备和网络块设备和网络设备设备设备设备,与此相关主要有三类设备驱动程序,字符设备驱动程,与此相关主要有三类设备驱动程序,字符设备驱动程,与此相关主要有三类设备驱动程序,字符设备驱动程,与此相关主要有三类设备驱动程序,字符设备驱动程序,块设备驱动程序和网络设备驱动程序序,块设备驱动程序和网络设备驱动程序序,块设备驱动程序和网络设备驱动程序序,块设备驱动程序和网络设备驱动程序. .n n他们的系统调用是一致的,他们的系统调用是一致的,他们的系统调用是一致的,他们的系统调用是一致的,采用统一的接口采用统一的接口采用统一的接口采用统一的接口( (在数据结构在数据结构在数据结构在数

11、据结构file_operationsfile_operations 中中中中) )。应用程序使用。应用程序使用。应用程序使用。应用程序使用设备设备设备设备就像使用就像使用就像使用就像使用读写普通的读写普通的读写普通的读写普通的文件一样文件一样文件一样文件一样方便方便方便方便, ,使用相同的使用相同的使用相同的使用相同的open(),close(),read(),write()open(),close(),read(),write()等等等等, ,真真真真正做到了与设备无关。正做到了与设备无关。正做到了与设备无关。正做到了与设备无关。6TM6ARM及Thumb指令集7.1.2 设备类型设备类型

12、n nLinuxLinux中的设备可以分为三类:中的设备可以分为三类:中的设备可以分为三类:中的设备可以分为三类:n n字符设备字符设备字符设备字符设备n n块设备块设备块设备块设备n n网络设备网络设备网络设备网络设备n n一个运行的一个运行的一个运行的一个运行的linuxlinux系统,当前使用的设备可以通过文件系统,当前使用的设备可以通过文件系统,当前使用的设备可以通过文件系统,当前使用的设备可以通过文件/proc/devices/proc/devices 查看。查看。查看。查看。7TM7ARM及Thumb指令集驱动程序中涉及的几个概念驱动程序中涉及的几个概念模块的概念模块的概念n nL

13、inuxLinux可以以可以以可以以可以以模块模块模块模块的形式的形式的形式的形式加载设备加载设备加载设备加载设备类型,通常来说类型,通常来说类型,通常来说类型,通常来说一个模块一个模块一个模块一个模块对应实现一个设备驱动对应实现一个设备驱动对应实现一个设备驱动对应实现一个设备驱动,因此是可以分类的。一般一个设,因此是可以分类的。一般一个设,因此是可以分类的。一般一个设,因此是可以分类的。一般一个设备驱动对应一类设备的模块方式,这样便于多个设备的协备驱动对应一类设备的模块方式,这样便于多个设备的协备驱动对应一类设备的模块方式,这样便于多个设备的协备驱动对应一类设备的模块方式,这样便于多个设备的

14、协调工作也利于应用程序的开发和扩展。调工作也利于应用程序的开发和扩展。调工作也利于应用程序的开发和扩展。调工作也利于应用程序的开发和扩展。n nLinuxLinux的驱动开发调试有两种方法:的驱动开发调试有两种方法:的驱动开发调试有两种方法:的驱动开发调试有两种方法:n n(1 1)直接编译到内核,再运行新的内核来测试;)直接编译到内核,再运行新的内核来测试;)直接编译到内核,再运行新的内核来测试;)直接编译到内核,再运行新的内核来测试;n n(2 2)编译为模块的形式,单独加载运行调试。)编译为模块的形式,单独加载运行调试。)编译为模块的形式,单独加载运行调试。)编译为模块的形式,单独加载运

15、行调试。 n n通常情况下设备驱动的通常情况下设备驱动的通常情况下设备驱动的通常情况下设备驱动的模块动态加载模块动态加载模块动态加载模块动态加载更为普遍,开发人员更为普遍,开发人员更为普遍,开发人员更为普遍,开发人员不必在调试过程中频繁启动机器就能完成设备驱动的开发不必在调试过程中频繁启动机器就能完成设备驱动的开发不必在调试过程中频繁启动机器就能完成设备驱动的开发不必在调试过程中频繁启动机器就能完成设备驱动的开发工作。工作。工作。工作。8TM8ARM及Thumb指令集n n模块加载与卸载模块加载与卸载模块加载与卸载模块加载与卸载 n n模块方式调试:模块方式调试:模块方式调试:模块方式调试:n

16、 n(1 1)编译的模块直接插入内核:用)编译的模块直接插入内核:用)编译的模块直接插入内核:用)编译的模块直接插入内核:用insmodinsmod 工具;工具;工具;工具;n n(2 2)从内核中卸载模块:用)从内核中卸载模块:用)从内核中卸载模块:用)从内核中卸载模块:用rmmodrmmod 。n n模模模模块块块块用用用用insmodinsmod命命命命令令令令加加加加载载载载,用用用用rmmodrmmod命命命命令令令令来来来来卸卸卸卸载载载载,这这这这两两两两个个个个命命命命令令令令分分分分 别别别别 调调调调 用用用用 module_init()module_init()和和和和

17、module_exitmodule_exit () ()函函函函 数数数数 , 还还还还 可可可可 以以以以 用用用用lsmodlsmod命令来查看所有已加载的模块的状态。命令来查看所有已加载的模块的状态。命令来查看所有已加载的模块的状态。命令来查看所有已加载的模块的状态。 n nLinuxLinux中模块可以用中模块可以用中模块可以用中模块可以用C C语言编写,用语言编写,用语言编写,用语言编写,用gccgcc命令命令命令命令编译成模块编译成模块编译成模块编译成模块*.ko*.ko9TM9ARM及Thumb指令集编写编写Hello World 模块模块n n#include#includen

18、 n#include#includen n#include#includen nMODULE_LICENSEMODULE_LICENSE(DualBSD/GPL);(DualBSD/GPL);n nstaticintstaticint_init_init hello_inithello_init(void)(void)n n n nprintk(printk(KERN_ALERTKERN_ALERTHello,World!n);Hello,World!n);n nreturn0;return0;n n n nstaticvoidstaticvoid_exit_exit hello_exithe

19、llo_exit(void)(void)n n n nprintk(KERN_ALERTGoodbye,world!n);printk(KERN_ALERTGoodbye,world!n);n n n nmodule_initmodule_init( (hello_inithello_init); );n nmodule_exitmodule_exit( (hello_exithello_exit); );定义定义定义定义_init_init、_exit_exit、module_initmodule_init、 module_exitmodule_exit所必需的宏所必需的宏所必需的宏所必需的

20、宏定义所有模块相关的宏定义所有模块相关的宏定义所有模块相关的宏定义所有模块相关的宏, ,比如比如比如比如MODULE_LICENSEMODULE_LICENSEmodule_init()module_init()、module_exit()module_exit()为内核特殊宏为内核特殊宏为内核特殊宏为内核特殊宏, ,分别用来定义模分别用来定义模分别用来定义模分别用来定义模块被装载和卸载时调用的函数块被装载和卸载时调用的函数块被装载和卸载时调用的函数块被装载和卸载时调用的函数定义定义定义定义printk()printk()中相关的宏中相关的宏中相关的宏中相关的宏, ,比比比比如如如如KERN_

21、ALERTKERN_ALERT10TM10ARM及Thumb指令集编写编写Hello World 模块模块n n#include#includen n#include#includen n#include#includen nMODULE_LICENSEMODULE_LICENSE(DualBSD/GPL);(DualBSD/GPL);n nstaticintstaticinthello_inithello_init(void)(void)n n n nprintk(printk(KERN_ALERTKERN_ALERTHello,World!n);Hello,World!n);n nretu

22、rn0;return0;n n n nstaticvoidstaticvoidhello_exithello_exit(void)(void)n n n nprintk(KERN_ALERTGoodbye,world!n);printk(KERN_ALERTGoodbye,world!n);n n n nmodule_initmodule_init( (hello_inithello_init); );n nmodule_exitmodule_exit( (hello_exithello_exit); );内核函数内核函数内核函数内核函数printkprintk被定义在被定义在被定义在被定义在

23、linuxlinux内核中内核中内核中内核中, ,他类似于标准他类似于标准他类似于标准他类似于标准C C函数函数函数函数printf().printf().用用用用MODULE_LICENSEMODULE_LICENSE宏来宏来宏来宏来声明该模块的许可协议声明该模块的许可协议声明该模块的许可协议声明该模块的许可协议, ,声明为声明为声明为声明为BSDBSD和和和和GPLGPL双重协议许可双重协议许可双重协议许可双重协议许可11TM11ARM及Thumb指令集编写编写Hello World 模块模块n nMODULE_AUTHORMODULE_AUTHOR(“BENSON”);/(“BENSON

24、”);/可选的可选的可选的可选的n nMODULE_DESCRIPTIONMODULE_DESCRIPTION(STUDY_MODULE);/(STUDY_MODULE);/可选的可选的可选的可选的12TM12ARM及Thumb指令集Printk函数函数n nprintk(printk(KERN_ALERTKERN_ALERTHello,World!n);Hello,World!n);n n问问问问: :为什么不用为什么不用为什么不用为什么不用printf()printf()函数呢函数呢函数呢函数呢? ?n n答答答答: :在讲交叉编译工具链的时候在讲交叉编译工具链的时候在讲交叉编译工具链的时

25、候在讲交叉编译工具链的时候, ,曾经讲到在曾经讲到在曾经讲到在曾经讲到在编译内核的时候编译内核的时候编译内核的时候编译内核的时候不能使用标准的不能使用标准的不能使用标准的不能使用标准的C C库和其他函数库的支持库和其他函数库的支持库和其他函数库的支持库和其他函数库的支持, ,所以不能使用所以不能使用所以不能使用所以不能使用printfprintf() ()库函数库函数库函数库函数n n内核有自己的打印函数内核有自己的打印函数内核有自己的打印函数内核有自己的打印函数printk(),printk(),它通过自身的运行而不需要它通过自身的运行而不需要它通过自身的运行而不需要它通过自身的运行而不需要

26、C C库的帮助库的帮助库的帮助库的帮助. .在使用在使用在使用在使用insmodinsmod装载之后装载之后装载之后装载之后, ,内核与内核公共函数和内核与内核公共函数和内核与内核公共函数和内核与内核公共函数和变量进行连接变量进行连接变量进行连接变量进行连接, ,从而可以使用从而可以使用从而可以使用从而可以使用printk()printk()函数函数函数函数. .n n其中其中其中其中KERN_ALERTKERN_ALERT宏是标记宏是标记宏是标记宏是标记printk()printk()打印出字符的打印出字符的打印出字符的打印出字符的优先等级优先等级优先等级优先等级的的的的, ,通常有八种消息

27、级别通常有八种消息级别通常有八种消息级别通常有八种消息级别, ,定义在定义在定义在定义在include/linux/kernel.hinclude/linux/kernel.h的文件的文件的文件的文件中中中中. .13TM13ARM及Thumb指令集n nprintk(printk(日志级别日志级别日志级别日志级别“ “消息文本消息文本消息文本消息文本”)”);n n这里的日志级别通俗的说指的是对这里的日志级别通俗的说指的是对这里的日志级别通俗的说指的是对这里的日志级别通俗的说指的是对文本信息的一种输出范围上的指定文本信息的一种输出范围上的指定文本信息的一种输出范围上的指定文本信息的一种输出范

28、围上的指定。n n#defineKERN_EMERG/*#defineKERN_EMERG/*紧急事件消息,系统崩溃之前提示,表紧急事件消息,系统崩溃之前提示,表紧急事件消息,系统崩溃之前提示,表紧急事件消息,系统崩溃之前提示,表示系统不可用示系统不可用示系统不可用示系统不可用*/*/n n#defineKERN_ALERT/*#defineKERN_ALERT/*报告消息,表示必须立即采取措施报告消息,表示必须立即采取措施报告消息,表示必须立即采取措施报告消息,表示必须立即采取措施*/*/n n#defineKERN_CRIT/*#defineKERN_CRIT/*临界条件,通常涉及严重的硬

29、件或软件操作临界条件,通常涉及严重的硬件或软件操作临界条件,通常涉及严重的硬件或软件操作临界条件,通常涉及严重的硬件或软件操作失败失败失败失败*/*/n n#defineKERN_ERR/*#defineKERN_ERR/*错误条件,驱动程序常用错误条件,驱动程序常用错误条件,驱动程序常用错误条件,驱动程序常用KERN_ERRKERN_ERR来报来报来报来报告硬件的错误告硬件的错误告硬件的错误告硬件的错误*/*/n n#defineKERN_WARNING/*#defineKERN_WARNING/*警告条件,对可能出现问题的情况进警告条件,对可能出现问题的情况进警告条件,对可能出现问题的情况

30、进警告条件,对可能出现问题的情况进行警告行警告行警告行警告*/*/n n#defineKERN_NOTICE/*#defineKERN_NOTICE/*正常但又重要的条件,用于提醒。常用正常但又重要的条件,用于提醒。常用正常但又重要的条件,用于提醒。常用正常但又重要的条件,用于提醒。常用于与安全相关的消息于与安全相关的消息于与安全相关的消息于与安全相关的消息*/*/n n#defineKERN_INFO/*#defineKERN_INFO/*提示信息,如驱动程序启动时,打印硬件信提示信息,如驱动程序启动时,打印硬件信提示信息,如驱动程序启动时,打印硬件信提示信息,如驱动程序启动时,打印硬件信息

31、息息息*/*/n n#defineKERN_DEBUG/*#defineKERN_DEBUG/*调试级别的消息调试级别的消息调试级别的消息调试级别的消息*/*/14TM14ARM及Thumb指令集linux2.4 编写编写Hello World 模块的模块的Makefilen nEXECEXEC=hello=hellon nOBJSOBJS=hello.o=hello.on nSRCSRC=hello.c= nINCLUDEINCLUDE=/usr/src/linux/fs2410_2.6.8/include=/usr/src/linux/fs2410_2.6.8/includen nCCCC

32、=/usr/local/3.3.2/bin/armlinuxgcc=/usr/local/3.3.2/bin/armlinuxgccn nLDLD=/usr/local/3.3.2/bin/armlinuxld=/usr/local/3.3.2/bin/armlinuxldn nMODCFLAGSMODCFLAGS=O2Wall=O2WallD_KERNEL_D_KERNEL_DMODULEDMODULEI I$(INCLUDE)$(INCLUDE) n nmarch=armv4tmarch=armv4tn nLDFLAGSLDFLAGS=r=rn nall:$(EXEC)all:$(EXEC

33、)n n$(EXEC):$(OBJS)$(EXEC):$(OBJS)n n$(LD)$(LDFLAGS)ohellohello.o$(LD)$(LDFLAGS)ohellohello.on n%.o:%.c%.o:%.cn n$(CC)$(MODCFLAGS)mapcsc$(CC)$(MODCFLAGS)mapcsc$o$o$n nclean:clean:n nrmf$(EXEC)*.o*corermf$(EXEC)*.o*core$:$:表示完整的目标文件表示完整的目标文件表示完整的目标文件表示完整的目标文件, ,包括包括包括包括扩展名扩展名扩展名扩展名$:$“”“发送文件发送文件发送文件发

34、送文件” ”,在弹出的对话框中设置如下:,在弹出的对话框中设置如下:,在弹出的对话框中设置如下:,在弹出的对话框中设置如下:19TM19ARM及Thumb指令集n n然后点击发送。数据传输完后,再回车,接着通过然后点击发送。数据传输完后,再回车,接着通过然后点击发送。数据传输完后,再回车,接着通过然后点击发送。数据传输完后,再回车,接着通过lsls来查看来查看来查看来查看/tmp/tmp目录下是否有目录下是否有目录下是否有目录下是否有hello.kohello.ko文件。文件。文件。文件。n n(4 4)hello.kohello.ko下载成功后,接下来我们要进行真正的加载下载成功后,接下来我

35、们要进行真正的加载下载成功后,接下来我们要进行真正的加载下载成功后,接下来我们要进行真正的加载和运行的工作了。和运行的工作了。和运行的工作了。和运行的工作了。 改变改变改变改变hello.kohello.ko的属性,命令如下:的属性,命令如下:的属性,命令如下:的属性,命令如下:n nchmod755hello.kochmod755hello.kon n(5 5)加载)加载)加载)加载hello.kohello.ko模块:模块:模块:模块:insmod./hello.koinsmod./hello.ko 这时我们就可以看到期待已久的这时我们就可以看到期待已久的这时我们就可以看到期待已久的这时我

36、们就可以看到期待已久的Hello,worldHello,world了。了。了。了。n n(6).(6).卸载驱动模块:卸载驱动模块:卸载驱动模块:卸载驱动模块:rmmodhello.kormmodhello.ko卸载时就可在屏幕上看到如下信息:卸载时就可在屏幕上看到如下信息:卸载时就可在屏幕上看到如下信息:卸载时就可在屏幕上看到如下信息: Goodbye,worldGoodbye,world20TM20ARM及Thumb指令集驱动程序中涉及的几个概念驱动程序中涉及的几个概念n n设备驱动程序的设备号和入口点设备驱动程序的设备号和入口点设备驱动程序的设备号和入口点设备驱动程序的设备号和入口点n

37、nLinuxLinux系统通过系统通过系统通过系统通过设备号设备号设备号设备号来区分不同设备。设备号由两部分组来区分不同设备。设备号由两部分组来区分不同设备。设备号由两部分组来区分不同设备。设备号由两部分组成:成:成:成:主设备号和次设备号。主设备号和次设备号。主设备号和次设备号。主设备号和次设备号。n n主设备号主设备号主设备号主设备号标识设备对应的驱动程序。系统中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以有相同的主设备号,主设备号相同的设备使用相同的驱动程有相同的主设备号,主设备号相同的

38、设备使用相同的驱动程有相同的主设备号,主设备号相同的设备使用相同的驱动程有相同的主设备号,主设备号相同的设备使用相同的驱动程序。序。序。序。 n n次设备号次设备号次设备号次设备号用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能有多个设备与之对应,这多个设备正是在有多个设备与之对应,这多个设备正是在有多个设备与之对应,这多个设备正是在有多个设备与之对应,这多个设备正是在驱动程序内通过次驱动程序内通过次驱动程序内通过次驱动程序内通过次设备号来进一步区分的设备号来进一步区

39、分的设备号来进一步区分的设备号来进一步区分的。次设备号只能由设备驱动程序使用,。次设备号只能由设备驱动程序使用,。次设备号只能由设备驱动程序使用,。次设备号只能由设备驱动程序使用,内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。n n在在在在/proc/devices/proc/devices 中列出了系统中处于中列出了系统中处于中列出了系统中处于中列出了系统中处于活动状态活动状态活动状态活动状态设备的主设备设备的主设备设备的主设备设备的主设备号,所谓的活动状态是指与

40、该设备对应的号,所谓的活动状态是指与该设备对应的号,所谓的活动状态是指与该设备对应的号,所谓的活动状态是指与该设备对应的设备驱动已经被系设备驱动已经被系设备驱动已经被系设备驱动已经被系统内核装载。统内核装载。统内核装载。统内核装载。21TM21ARM及Thumb指令集/dev/字符为字符为字符为字符为c c c c表示字表示字表示字表示字符设备符设备符设备符设备, , , ,为为为为b b b b表表表表示块设备示块设备示块设备示块设备两个数字对应两个数字对应两个数字对应两个数字对应主设备号和次主设备号和次主设备号和次主设备号和次设备号设备号设备号设备号n n对于现有对于现有对于现有对于现有L

41、inuxLinux操作操作操作操作系统,系统,系统,系统,/dev/dev目录是必不目录是必不目录是必不目录是必不可少的,这个目录包含可少的,这个目录包含可少的,这个目录包含可少的,这个目录包含了所有了所有了所有了所有LinuxLinux系统所知系统所知系统所知系统所知道的字符设备,块设备道的字符设备,块设备道的字符设备,块设备道的字符设备,块设备和网络设备和网络设备和网络设备和网络设备22TM22ARM及Thumb指令集/proc/devicesp233在在在在/proc/devices/proc/devices/proc/devices/proc/devices 中列出了系统中处中列出了系

42、统中处中列出了系统中处中列出了系统中处于于于于活动状态活动状态活动状态活动状态设备的设备的设备的设备的主设备号主设备号主设备号主设备号23TM23ARM及Thumb指令集dev_t类型类型n ndev_tdev_t类型类型类型类型n n内核用内核用内核用内核用dev_tdev_t类型来保存类型来保存类型来保存类型来保存设备编号设备编号设备编号设备编号,dev_tdev_t是个是个是个是个3232位的数,位的数,位的数,位的数,1212位位位位表示主设备号,表示主设备号,表示主设备号,表示主设备号,2020为表示次设备号。在实际使用中,是通过中为表示次设备号。在实际使用中,是通过中为表示次设备号

43、。在实际使用中,是通过中为表示次设备号。在实际使用中,是通过中定义的宏来转换格式。定义的宏来转换格式。定义的宏来转换格式。定义的宏来转换格式。n n获得获得获得获得dev_tdev_t的主设备号和次设备号,应使用以下的宏,例如:的主设备号和次设备号,应使用以下的宏,例如:的主设备号和次设备号,应使用以下的宏,例如:的主设备号和次设备号,应使用以下的宏,例如:n ndev_t dev_t devdev; ;n nMAJOR(MAJOR(devdev); /*); /*主设备号主设备号主设备号主设备号*/*/n n MINOR( MINOR(devdev); /*); /*次设备号次设备号次设备号

44、次设备号*/*/n n如果要将主设备号、次设备号转换成如果要将主设备号、次设备号转换成如果要将主设备号、次设备号转换成如果要将主设备号、次设备号转换成dev_tdev_t类型,则使用以下类型,则使用以下类型,则使用以下类型,则使用以下的宏的宏的宏的宏, ,例如:例如:例如:例如:n nInt major=4, minor=3;Int major=4, minor=3;n nMKDEV(int major,int minor)MKDEV(int major,int minor)24TM24ARM及Thumb指令集设备入口点设备入口点p234n n设备入口点设备入口点设备入口点设备入口点n n设备

45、入口点也可以理解为设备入口点也可以理解为设备入口点也可以理解为设备入口点也可以理解为“ “设备文件句柄设备文件句柄设备文件句柄设备文件句柄” ”,一个设备的入口,一个设备的入口,一个设备的入口,一个设备的入口点和磁盘上的普通文件系统一样,可以删除(点和磁盘上的普通文件系统一样,可以删除(点和磁盘上的普通文件系统一样,可以删除(点和磁盘上的普通文件系统一样,可以删除(rmrm), ,移动移动移动移动(mvmv)和复制()和复制()和复制()和复制(cpcp)等。)等。)等。)等。n n我们可以在文件系统中使用我们可以在文件系统中使用我们可以在文件系统中使用我们可以在文件系统中使用mknodmkn

46、od命令创建一个设备入口点。命令创建一个设备入口点。命令创建一个设备入口点。命令创建一个设备入口点。在文件系统中创建了设备入口点并在文件系统中创建了设备入口点并在文件系统中创建了设备入口点并在文件系统中创建了设备入口点并没有代表响应的设备驱动没有代表响应的设备驱动没有代表响应的设备驱动没有代表响应的设备驱动和硬件已经准备好和硬件已经准备好和硬件已经准备好和硬件已经准备好,只是代表了和设备驱动通信的一部分。只是代表了和设备驱动通信的一部分。只是代表了和设备驱动通信的一部分。只是代表了和设备驱动通信的一部分。n n下面给一个创建字符设备入口点的实例:下面给一个创建字符设备入口点的实例:下面给一个创

47、建字符设备入口点的实例:下面给一个创建字符设备入口点的实例:n nmknod/mknod/devdev/testChar/testCharc c 10001000n n其中其中其中其中c c代表字符设备,如果想创建块设备则用代表字符设备,如果想创建块设备则用代表字符设备,如果想创建块设备则用代表字符设备,如果想创建块设备则用bb代替代替代替代替c c。参数。参数。参数。参数100100代表该设备的主设备号,代表该设备的主设备号,代表该设备的主设备号,代表该设备的主设备号,0 0代表该设备的次设备号。代表该设备的次设备号。代表该设备的次设备号。代表该设备的次设备号。25TM25ARM及Thumb

48、指令集设备入口点设备入口点创建设备的入口点之后,可以通过如下命令查看:创建设备的入口点之后,可以通过如下命令查看:创建设备的入口点之后,可以通过如下命令查看:创建设备的入口点之后,可以通过如下命令查看:n nlsl/dev/testCharlsl/dev/testCharn n删除设备入口点也非常简单:删除设备入口点也非常简单:删除设备入口点也非常简单:删除设备入口点也非常简单:n nrm/dev/testCharrm/dev/testChar26TM26ARM及Thumb指令集用户空间和内核空间用户空间和内核空间p220n n设备驱动设备驱动设备驱动设备驱动运行在运行在运行在运行在内核空间内

49、核空间内核空间内核空间( (在一些操作系统的书籍里面称为在一些操作系统的书籍里面称为在一些操作系统的书籍里面称为在一些操作系统的书籍里面称为“ “系统态系统态系统态系统态”)”),n n而而而而应用程序应用程序应用程序应用程序则运行在则运行在则运行在则运行在用户空间用户空间用户空间用户空间( (也可称为也可称为也可称为也可称为“ “用户态用户态用户态用户态”)”)。n n设备设备设备设备驱动程序驱动程序驱动程序驱动程序运行在内核空间比应用程序执行的运行在内核空间比应用程序执行的运行在内核空间比应用程序执行的运行在内核空间比应用程序执行的优先级要高优先级要高优先级要高优先级要高很多很多很多很多。

50、内核态具有最高的运行级别,可以做任何事。内核态具有最高的运行级别,可以做任何事。内核态具有最高的运行级别,可以做任何事。内核态具有最高的运行级别,可以做任何事。n n应用程序应用程序应用程序应用程序则运行在则运行在则运行在则运行在最低级别的用户态最低级别的用户态最低级别的用户态最低级别的用户态,在这一级别处理器,在这一级别处理器,在这一级别处理器,在这一级别处理器禁禁禁禁止对硬件的直接访问止对硬件的直接访问止对硬件的直接访问止对硬件的直接访问和对内存的未授权访问。和对内存的未授权访问。和对内存的未授权访问。和对内存的未授权访问。n n内核空间和用户空间分别引用不同的内存映射内核空间和用户空间分

51、别引用不同的内存映射内核空间和用户空间分别引用不同的内存映射内核空间和用户空间分别引用不同的内存映射,也就是程序,也就是程序,也就是程序,也就是程序代码使用不同的代码使用不同的代码使用不同的代码使用不同的地址空间地址空间地址空间地址空间. .n nLinuxLinux操作系统通过操作系统通过操作系统通过操作系统通过系统调用和硬件中断系统调用和硬件中断系统调用和硬件中断系统调用和硬件中断完成从用户空间到完成从用户空间到完成从用户空间到完成从用户空间到内核空间的控制转移。内核空间的控制转移。内核空间的控制转移。内核空间的控制转移。27TM27ARM及Thumb指令集字符设备字符设备p218n n字

52、符设备字符设备字符设备字符设备: :字符设备按照字符流的方式被字符设备按照字符流的方式被字符设备按照字符流的方式被字符设备按照字符流的方式被有序访问有序访问有序访问有序访问,像串口,像串口,像串口,像串口和键盘就都属于字符设备。如果一个硬件设备是以字符流的和键盘就都属于字符设备。如果一个硬件设备是以字符流的和键盘就都属于字符设备。如果一个硬件设备是以字符流的和键盘就都属于字符设备。如果一个硬件设备是以字符流的方式被访问的话,那就应该将它归于字符设备;方式被访问的话,那就应该将它归于字符设备;方式被访问的话,那就应该将它归于字符设备;方式被访问的话,那就应该将它归于字符设备;n n字符设备是字符

53、设备是字符设备是字符设备是linuxlinux最简单的设备最简单的设备最简单的设备最简单的设备, ,可以像文件一样访问可以像文件一样访问可以像文件一样访问可以像文件一样访问, ,区别主区别主区别主区别主要在于要在于要在于要在于: :普通文件可以来普通文件可以来普通文件可以来普通文件可以来/ /回读回读回读回读/ /写写写写, ,而字符设备只能是而字符设备只能是而字符设备只能是而字符设备只能是顺序读顺序读顺序读顺序读/ /写写写写. .我们可以对其调用我们可以对其调用我们可以对其调用我们可以对其调用打开、读取、写和关闭打开、读取、写和关闭打开、读取、写和关闭打开、读取、写和关闭。n n初始化字符

54、设备时,驱动程序向初始化字符设备时,驱动程序向初始化字符设备时,驱动程序向初始化字符设备时,驱动程序向linuxlinux登记登记登记登记,并在字符设备向,并在字符设备向,并在字符设备向,并在字符设备向量中增加一个量中增加一个量中增加一个量中增加一个device_structdevice_struct数据结构条目数据结构条目数据结构条目数据结构条目,这个设备的,这个设备的,这个设备的,这个设备的主设主设主设主设备标识备标识备标识备标识符(符(符(符(ttytty的主设备号为的主设备号为的主设备号为的主设备号为4 4)用作这个向量表的)用作这个向量表的)用作这个向量表的)用作这个向量表的索引索引

55、索引索引28TM28ARM及Thumb指令集系统调用系统调用n n系统调用系统调用系统调用系统调用n n字符设备是字符设备是字符设备是字符设备是linuxlinux最简单的设备最简单的设备最简单的设备最简单的设备, ,可以像文件一样访问可以像文件一样访问可以像文件一样访问可以像文件一样访问. .n n所以在用户空间中所以在用户空间中所以在用户空间中所以在用户空间中, ,系统进程(应用程序)系统进程(应用程序)系统进程(应用程序)系统进程(应用程序)对设备文件的操作对设备文件的操作对设备文件的操作对设备文件的操作通过通过通过通过系统调用来完成系统调用来完成系统调用来完成系统调用来完成,如,如,如

56、,如openopen、readread、writewrite、closeclose等。等。等。等。n n下面通过一个简单的例子来了解一下系统调用的使用:下面通过一个简单的例子来了解一下系统调用的使用:下面通过一个简单的例子来了解一下系统调用的使用:下面通过一个简单的例子来了解一下系统调用的使用:29TM29ARM及Thumb指令集一个简单的应用程序一个简单的应用程序n n#defineDEVICE_GPIOTEST#defineDEVICE_GPIOTEST“/dev/gpio”“/dev/gpio”/设备入口点设备入口点设备入口点设备入口点n nintmain(intargc,char*ar

57、gv)intmain(intargc,char*argv)n nintfd;intfd;n nintval=1;intval=1;n nfd=open(fd=open(DEVICE_GPIOTESTDEVICE_GPIOTEST,O_RDONLY);/,O_RDONLY);/打开设备打开设备打开设备打开设备n nif(if(fdfd0)/0)/fdfd为返回的设备文件描述字为返回的设备文件描述字为返回的设备文件描述字为返回的设备文件描述字handlehandle n n n nperror(cannotopendevice);perror(cannotopendevice);n nexit(1

58、);exit(1);n n n nwhile(1)while(1)n nprintf(pleaseselectnumbertorunprogramn);printf(pleaseselectnumbertorunprogramn);n nprintf(1:ledonn2:quit);printf(1:ledonn2:quit);30TM30ARM及Thumb指令集一个简单的应用程序一个简单的应用程序n nscanf(%d,&val);scanf(%d,&val);n nif(val=1)if(val=1)n nioctlioctl(fd,1,10);(fd,1,10);/*/*主要用于对设备进

59、行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制*/*/n nelseif(val=2)elseif(val=2)n ncloseclose(fd);/*(fd);/*关闭设备关闭设备关闭设备关闭设备*/*/n n n n n nreturn0;return0;n n 31TM31ARM及Thumb指令集设备驱动和文件系统的关系设备驱动和文件系统的关系 n open 打开设备准备I/O操作。 openopen打开设备准备打开设备准备打开设备准备打开设备准备I/OI/O操作。操作。操作。操作。 其调用格式为其调用格式

60、为其调用格式为其调用格式为: :intintopen(char*filename,open(char*filename,intintaccess);access); 该函数返回该函数返回该函数返回该函数返回文件描述字文件描述字文件描述字文件描述字handlehandle ,如果,如果,如果,如果返回值小于返回值小于返回值小于返回值小于0, 0,表示打开设备文表示打开设备文表示打开设备文表示打开设备文件失败件失败件失败件失败32TM32ARM及Thumb指令集n ncloseclose()closeclose()函数函数函数函数的作用是关闭由的作用是关闭由的作用是关闭由的作用是关闭由open()

61、open()函数打开的文件函数打开的文件函数打开的文件函数打开的文件, ,其其其其调用格式为调用格式为调用格式为调用格式为:intclose(inthandle);intclose(inthandle);n n该函数关闭文件描述字该函数关闭文件描述字该函数关闭文件描述字该函数关闭文件描述字handlehandle相连的文件。相连的文件。相连的文件。相连的文件。n n readread从设备上读数据从设备上读数据从设备上读数据从设备上读数据。对于有缓冲区的。对于有缓冲区的。对于有缓冲区的。对于有缓冲区的I/OI/O操作,一般是操作,一般是操作,一般是操作,一般是从缓冲区里读数据。从缓冲区里读数据

62、。从缓冲区里读数据。从缓冲区里读数据。n nwritewrite往设备上写数据往设备上写数据往设备上写数据往设备上写数据,对于有缓冲区的,对于有缓冲区的,对于有缓冲区的,对于有缓冲区的I/OI/O操作,一般是操作,一般是操作,一般是操作,一般是把数据写入缓冲区里。把数据写入缓冲区里。把数据写入缓冲区里。把数据写入缓冲区里。write()write()函数的调用格式为:函数的调用格式为:函数的调用格式为:函数的调用格式为:n nintwrite(inthandle,void*buf,intcount);intwrite(inthandle,void*buf,intcount);n nwrite(

63、)write()函数把函数把函数把函数把countcount个字节从个字节从个字节从个字节从bufbuf指向的缓冲区写入与指向的缓冲区写入与指向的缓冲区写入与指向的缓冲区写入与handlehandle相相相相连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。 7.1.1 设备驱动和文件系统的关系设备驱动和文件系统的关系 33TM33ARM及Thumb指令集n nioctlioctl主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用

64、于对设备进行读写之外的其他控制。用户空间的。用户空间的。用户空间的。用户空间的ioctlioctl函数的原型为:函数的原型为:函数的原型为:函数的原型为:intioctl(inffd,intcmd,)intioctl(inffd,intcmd,)n n其中的其中的其中的其中的代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般定义为定义为定义为定义为:intioctl(inffd,intcmd,char*argp)intioctl(inffd,intcmd

65、,char*argp)n n其中其中其中其中fdfd为为为为文件描述字文件描述字文件描述字文件描述字handlehandlen ncmdcmd为命令字为命令字为命令字为命令字, ,不同的命令字对应不同的操作不同的命令字对应不同的操作不同的命令字对应不同的操作不同的命令字对应不同的操作. .34TM34ARM及Thumb指令集7.1.1 设备驱动和文件系统的关系设备驱动和文件系统的关系 n open 打开设备准备I/O操作。 openopen打开设备准备打开设备准备打开设备准备打开设备准备I/OI/O操作。操作。操作。操作。该函数返回文件描述字该函数返回文件描述字该函数返回文件描述字该函数返回文

66、件描述字handlehandle 其调用格式为其调用格式为其调用格式为其调用格式为: :intintopen(char*filename,open(char*filename,intintaccess);access);35TM35ARM及Thumb指令集n ncloseclose()closeclose()函数函数函数函数的作用是关闭由的作用是关闭由的作用是关闭由的作用是关闭由open()open()函数打开的文件函数打开的文件函数打开的文件函数打开的文件, ,其其其其调用格式为调用格式为调用格式为调用格式为:intclose(inthandle);intclose(inthandle);n

67、 n该函数关闭文件描述字该函数关闭文件描述字该函数关闭文件描述字该函数关闭文件描述字handlehandle相连的文件。相连的文件。相连的文件。相连的文件。n n readread从设备上读数据从设备上读数据从设备上读数据从设备上读数据。对于有缓冲区的。对于有缓冲区的。对于有缓冲区的。对于有缓冲区的I/OI/O操作,一般是操作,一般是操作,一般是操作,一般是从缓冲区里读数据。从缓冲区里读数据。从缓冲区里读数据。从缓冲区里读数据。n nwritewrite往设备上写数据往设备上写数据往设备上写数据往设备上写数据,对于有缓冲区的,对于有缓冲区的,对于有缓冲区的,对于有缓冲区的I/OI/O操作,一般

68、是操作,一般是操作,一般是操作,一般是把数据写入缓冲区里。把数据写入缓冲区里。把数据写入缓冲区里。把数据写入缓冲区里。write()write()函数的调用格式为:函数的调用格式为:函数的调用格式为:函数的调用格式为:n nintwrite(inthandle,void*buf,intcount);intwrite(inthandle,void*buf,intcount);n nwrite()write()函数把函数把函数把函数把countcount个字节从个字节从个字节从个字节从bufbuf指向的缓冲区写入与指向的缓冲区写入与指向的缓冲区写入与指向的缓冲区写入与handlehandle相相相

69、相连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。连的文件中,返回值为实际写入的字节数。 7.1.1 设备驱动和文件系统的关系设备驱动和文件系统的关系 36TM36ARM及Thumb指令集n nioctlioctl主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制主要用于对设备进行读写之外的其他控制。用户空间的。用户空间的。用户空间的。用户空间的ioctlioctl函数的原型为:函数的原型为:函数的原型为:函数的原型为:intioctl(inffd,intcmd,)int

70、ioctl(inffd,intcmd,)n n其中的其中的其中的其中的代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般代表可变数目的参数表,实际中是一个可选参数,一般定义为定义为定义为定义为:intioctl(inffd,intcmd,char*argp)intioctl(inffd,intcmd,char*argp)n n驱动程序中定义的驱动程序中定义的驱动程序中定义的驱动程序中定义的ioctlioctl方法原型为:方法原型为:方法原型为:方法原型为:n nint(*ioctl)(structin

71、ode*inode,structfile*file,unsignedintcmd,int(*ioctl)(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)unsignedlongarg)n ninodeinode和和和和filpfilp两个指针对应应用程序传递的文件描述符两个指针对应应用程序传递的文件描述符两个指针对应应用程序传递的文件描述符两个指针对应应用程序传递的文件描述符fdfd、cmdcmd不不不不会被修改地传递给驱动程序,可选的参数会被修改地传递给驱动程序,可选的参数会被修改地传递给驱动程序,可选的参数

72、会被修改地传递给驱动程序,可选的参数argarg则无论用户应用程序则无论用户应用程序则无论用户应用程序则无论用户应用程序使用的是指针还是其他类型值,都以使用的是指针还是其他类型值,都以使用的是指针还是其他类型值,都以使用的是指针还是其他类型值,都以unsignedlongunsignedlong的形式传递给驱的形式传递给驱的形式传递给驱的形式传递给驱动。动。动。动。37TM37ARM及Thumb指令集7.1.3 设备号设备号 n nlinux/uclinuxlinux/uclinux内核还需要内核还需要内核还需要内核还需要: :n n主设备号主设备号主设备号主设备号标识设备对应的驱动程序。系统

73、中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以标识设备对应的驱动程序。系统中不同的设备可以有相同的主设备号,主设备号相同的设备使用相同的驱动程有相同的主设备号,主设备号相同的设备使用相同的驱动程有相同的主设备号,主设备号相同的设备使用相同的驱动程有相同的主设备号,主设备号相同的设备使用相同的驱动程序。序。序。序。 n n次设备号次设备号次设备号次设备号用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能用来区分具体驱动程序的实例。一个主设备号可能有多个设备与

74、之对应,这多个设备正是在驱动程序内通过次有多个设备与之对应,这多个设备正是在驱动程序内通过次有多个设备与之对应,这多个设备正是在驱动程序内通过次有多个设备与之对应,这多个设备正是在驱动程序内通过次设备号来进一步区分的。次设备号只能由设备驱动程序使用,设备号来进一步区分的。次设备号只能由设备驱动程序使用,设备号来进一步区分的。次设备号只能由设备驱动程序使用,设备号来进一步区分的。次设备号只能由设备驱动程序使用,内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。内核的其他部分仅将它作为参数传递给驱动程序。38TM38

75、ARM及Thumb指令集字符型设备主设备号的添加和注销字符型设备主设备号的添加和注销 n n字符型设备主设备号的添加和注销分别通过调用函数字符型设备主设备号的添加和注销分别通过调用函数字符型设备主设备号的添加和注销分别通过调用函数字符型设备主设备号的添加和注销分别通过调用函数register_chrdevregister_chrdev() ()和和和和unregister_chrdev()unregister_chrdev()实现,这两个函数原型在实现,这两个函数原型在实现,这两个函数原型在实现,这两个函数原型在文件说文件说文件说文件说明。明。明。明。n nexternintregister_

76、chrdev(unsignedintmajor,constchar*name,externintregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);structfile_operations*fops);n nexternintunregister_chrdev(unsignedintmajor,constcharexternintunregister_chrdev(unsignedintmajor,constchar*name);*name);39TM39ARM及Thumb指令集7.2设备驱动

77、程序基础设备驱动程序基础n 7.2.1 7.2.1 7.2.1 7.2.1 设备驱动中关键数据结构设备驱动中关键数据结构设备驱动中关键数据结构设备驱动中关键数据结构n n在在在在linuxlinux系统中,设备驱动程序所提供的这组入口点由系统中,设备驱动程序所提供的这组入口点由系统中,设备驱动程序所提供的这组入口点由系统中,设备驱动程序所提供的这组入口点由一个文件操作结构进行说明,分别是一个文件操作结构进行说明,分别是一个文件操作结构进行说明,分别是一个文件操作结构进行说明,分别是: :n nfile_operations(file_operations(文件操作文件操作文件操作文件操作) )

78、数据结构数据结构数据结构数据结构 n nfilefile数据结构数据结构数据结构数据结构n ninodeinode数据结构数据结构数据结构数据结构 n n它们定义于它们定义于它们定义于它们定义于Linux/fs.hLinux/fs.h文件中。文件中。文件中。文件中。 40TM40ARM及Thumb指令集file_operations(文件操作文件操作)数据结构数据结构n n由于由于由于由于用户进程用户进程用户进程用户进程是通过是通过是通过是通过设备文件设备文件设备文件设备文件同同同同硬件硬件硬件硬件打交道的,所以对设备打交道的,所以对设备打交道的,所以对设备打交道的,所以对设备文件的操作不外乎

79、一些系统调用,如文件的操作不外乎一些系统调用,如文件的操作不外乎一些系统调用,如文件的操作不外乎一些系统调用,如openopen、readread、writewrite、closeclose等。等。等。等。n n但是如何把系统调用和驱动程序关联起来但是如何把系统调用和驱动程序关联起来但是如何把系统调用和驱动程序关联起来但是如何把系统调用和驱动程序关联起来,这里需要一个非,这里需要一个非,这里需要一个非,这里需要一个非常关键的数据结构,既常关键的数据结构,既常关键的数据结构,既常关键的数据结构,既file_operationsfile_operations(文件操作)。文件操作)。文件操作)。文

80、件操作)。n n它用来它用来它用来它用来存储存储存储存储驱动内核模块提供的驱动内核模块提供的驱动内核模块提供的驱动内核模块提供的对设备进行的各种操作的对设备进行的各种操作的对设备进行的各种操作的对设备进行的各种操作的函函函函数指针数指针数指针数指针。41TM41ARM及Thumb指令集1. file_operations数据结构数据结构 n nstructfile_operationsstructfile_operationsn nstructmodule*owner;structmodule*owner;n nloff_t(*llseek)(structfile*,loff_t,int);l

81、off_t(*llseek)(structfile*,loff_t,int);n nssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*read)(structfile*,char*,size_t,loff_t*);n nssize_t(*write)(structfile*,constchar*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);n nint(*readdir)(structfile*,void*,filldir_t);i

82、nt(*readdir)(structfile*,void*,filldir_t);n nunsignedint(*poll)(structfile*,structpoll_table_struct*);unsignedint(*poll)(structfile*,structpoll_table_struct*);n nint(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);n nint(*mmap

83、)(structfile*,structvm_area_struct*);int(*mmap)(structfile*,structvm_area_struct*);n nint(*open)(structinode*,structfile*);int(*open)(structinode*,structfile*);n nint(*flush)(structfile*);int(*flush)(structfile*);结构体中的每结构体中的每结构体中的每结构体中的每一个成员都对一个成员都对一个成员都对一个成员都对应着应着应着应着驱动内核驱动内核驱动内核驱动内核模块用来处理模块用来处理模块用

84、来处理模块用来处理某个请求事物某个请求事物某个请求事物某个请求事物的函数的地址的函数的地址的函数的地址的函数的地址42TM42ARM及Thumb指令集n nint(*release)(structinode*,structfile*);int(*release)(structinode*,structfile*);n nint(*fsync)(structfile*,structdentry*,intdatasync);int(*fsync)(structfile*,structdentry*,intdatasync);n nint(*fasync)(int,structfile*,int);

85、int(*fasync)(int,structfile*,int);n nint(*lock)(structfile*,int,structfile_lock*);int(*lock)(structfile*,int,structfile_lock*);n nssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);n nssize_t(*writev)(structfile*,co

86、nststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);n nssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);n nunsignedunsigned longlong (*get_unmapped_area)(struct

87、(*get_unmapped_area)(struct filefile *,unsigned*,unsigned long,unsignedlong,unsignedlong,unsignedlong,unsignedlong);long,unsignedlong,unsignedlong);n n; ;43TM43ARM及Thumb指令集p228n n在在在在simplesimple设备驱动程序中它的设备驱动程序中它的设备驱动程序中它的设备驱动程序中它的file_operationsfile_operations结构是如下初结构是如下初结构是如下初结构是如下初始化的始化的始化的始化的: :

88、n nstructfile_operationsstructfile_operationssimple_fopssimple_fops=n n.owner=THIS_MODULE,.owner=THIS_MODULE,n n.llseek=simple_llseek,.llseek=simple_llseek,n n.read=simple_read,.read=simple_read,n n.write=simple_write,.write=simple_write,n n.ioctl=simple_ioctl,.ioctl=simple_ioctl,n n.open=.open=simp

89、le_opensimple_open, ,n n.release=simple_release,;.release=simple_release,; 对对对对simple_fopssimple_fops变量进变量进变量进变量进行初始化行初始化行初始化行初始化 将对应操作的将对应操作的将对应操作的将对应操作的函数名函数名函数名函数名作为作为作为作为指针指针指针指针传递给相应传递给相应传递给相应传递给相应的成员的成员的成员的成员44TM44ARM及Thumb指令集n n在在在在file_operationsfile_operations数数数数据据据据结结结结构构构构中中中中,指指指指出出出出了了

90、了了设设设设备备备备驱驱驱驱动动动动程程程程序序序序所所所所提提提提供供供供的的的的入入入入口口口口点位置,分别是:点位置,分别是:点位置,分别是:点位置,分别是:n n1)structmodule*owner1)structmodule*ownern n该成员是该成员是该成员是该成员是file_operationsfile_operations结构中唯一一个不是声明操作的成员结构中唯一一个不是声明操作的成员结构中唯一一个不是声明操作的成员结构中唯一一个不是声明操作的成员; ;它它它它是一个指向拥有这个结构的模块的指针是一个指向拥有这个结构的模块的指针是一个指向拥有这个结构的模块的指针是一个指

91、向拥有这个结构的模块的指针. .这个成员用来在它的操作这个成员用来在它的操作这个成员用来在它的操作这个成员用来在它的操作还在被使用时阻止模块被卸载还在被使用时阻止模块被卸载还在被使用时阻止模块被卸载还在被使用时阻止模块被卸载. .几乎所有时间中几乎所有时间中几乎所有时间中几乎所有时间中, ,它被简单初始化为它被简单初始化为它被简单初始化为它被简单初始化为 THIS_MODULETHIS_MODULE, ,一个在一个在一个在一个在中定义的宏中定义的宏中定义的宏中定义的宏. .n n2)loff_t(*llseek)(structfile*,loff_t,int);2)loff_t(*llseek

92、)(structfile*,loff_t,int);n nllseekllseek方法用作改变文件中的当前读方法用作改变文件中的当前读方法用作改变文件中的当前读方法用作改变文件中的当前读/ /写位置写位置写位置写位置, ,并且新位置作为并且新位置作为并且新位置作为并且新位置作为( (正正正正的的的的) )返回值返回值返回值返回值. .loff_tloff_t参数参数参数参数是一个是一个是一个是一个longoffset,longoffset,并且就算在并且就算在并且就算在并且就算在3232位平台上位平台上位平台上位平台上也至少也至少也至少也至少6464位宽位宽位宽位宽. .错误由一个负返回值指示

93、错误由一个负返回值指示错误由一个负返回值指示错误由一个负返回值指示. .45TM45ARM及Thumb指令集n n3)ssize_t(*read)(structfile*,char_user*,size_t,loff_t*);3)ssize_t(*read)(structfile*,char_user*,size_t,loff_t*);n n用来从设备中获取数据用来从设备中获取数据用来从设备中获取数据用来从设备中获取数据. .当为空时当为空时当为空时当为空时, ,导致导致导致导致 readread系统调用系统调用系统调用系统调用以以以以 EINVAL(“Invalidargument”)EIN

94、VAL(“Invalidargument”)失败失败失败失败. .一个非负返回值代表了一个非负返回值代表了一个非负返回值代表了一个非负返回值代表了成功读取的字节数成功读取的字节数成功读取的字节数成功读取的字节数n n其中其中其中其中ssize_tssize_t为为为为intint或或或或longlong型型型型, ,和平台相关和平台相关和平台相关和平台相关,_user,_user用来声明为用用来声明为用用来声明为用用来声明为用户态户态户态户态n n4)ssize_t(*aio_read)(structkiocb*,char_user*,size_t,4)ssize_t(*aio_read)(s

95、tructkiocb*,char_user*,size_t,loff_t);loff_t);n n初始化一个异步读初始化一个异步读初始化一个异步读初始化一个异步读可能在函数返回前不结束的读操作可能在函数返回前不结束的读操作可能在函数返回前不结束的读操作可能在函数返回前不结束的读操作. .如如如如果这个方法是果这个方法是果这个方法是果这个方法是NULL,NULL,所有的操作会由所有的操作会由所有的操作会由所有的操作会由readread代替进行代替进行代替进行代替进行( (同步同步同步同步地地地地). ).46TM46ARM及Thumb指令集n n5)ssize_t(*write)(structf

96、ile*,constchar_user*,size_t,5)ssize_t(*write)(structfile*,constchar_user*,size_t,loff_t*)loff_t*)n n发送数据给设备发送数据给设备发送数据给设备发送数据给设备. .如果如果如果如果NULL,EINVALNULL,EINVAL返回给调用返回给调用返回给调用返回给调用writewrite系系系系统调用的程序统调用的程序统调用的程序统调用的程序. .如果非负如果非负如果非负如果非负, ,返回值代表成功写的字节数返回值代表成功写的字节数返回值代表成功写的字节数返回值代表成功写的字节数. .n n6)ssi

97、ze_t(*aio_write)(structkiocb*,constchar_user*,6)ssize_t(*aio_write)(structkiocb*,constchar_user*,size_t,loff_t*);size_t,loff_t*);n n初始化设备上的一个异步写初始化设备上的一个异步写初始化设备上的一个异步写初始化设备上的一个异步写. .n n7)int(*readdir)(structfile*,void*,filldir_t);7)int(*readdir)(structfile*,void*,filldir_t);n n对于设备文件这个成员应当为对于设备文件这个

98、成员应当为对于设备文件这个成员应当为对于设备文件这个成员应当为NULL;NULL;它用来读取目录它用来读取目录它用来读取目录它用来读取目录, ,并且并且并且并且仅对文件系统有用仅对文件系统有用仅对文件系统有用仅对文件系统有用. .47TM47ARM及Thumb指令集n nunsignedint(*poll)(structfile*,structpoll_table_struct*);unsignedint(*poll)(structfile*,structpoll_table_struct*);n npollpoll方法用作查询对一个或多个文件描述符的读或写是否会方法用作查询对一个或多个文件描

99、述符的读或写是否会方法用作查询对一个或多个文件描述符的读或写是否会方法用作查询对一个或多个文件描述符的读或写是否会阻塞阻塞阻塞阻塞.poll.poll方法应当返回一个位掩码指示是否非阻塞的读或方法应当返回一个位掩码指示是否非阻塞的读或方法应当返回一个位掩码指示是否非阻塞的读或方法应当返回一个位掩码指示是否非阻塞的读或写是可能的写是可能的写是可能的写是可能的, ,并且并且并且并且, ,可能地可能地可能地可能地, ,提供给内核信息用来使调用进程提供给内核信息用来使调用进程提供给内核信息用来使调用进程提供给内核信息用来使调用进程睡眠直到睡眠直到睡眠直到睡眠直到I/OI/O变为可能变为可能变为可能变为

100、可能. .如果一个驱动的如果一个驱动的如果一个驱动的如果一个驱动的pollpoll方法为方法为方法为方法为NULL,NULL,设备假定为不阻塞地可读可写设备假定为不阻塞地可读可写设备假定为不阻塞地可读可写设备假定为不阻塞地可读可写. .n nint(*ioctl)(structinode*,structfile*,unsignedint,unsignedint(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);long);n nioctlioctl系统调用提供了发出设备特定命令的方法系统调用提供了发出设备特定命令的方法系统调用

101、提供了发出设备特定命令的方法系统调用提供了发出设备特定命令的方法. .如果设备不如果设备不如果设备不如果设备不提供提供提供提供ioctlioctl方法方法方法方法, ,系统调用将返回一个错误系统调用将返回一个错误系统调用将返回一个错误系统调用将返回一个错误. .48TM48ARM及Thumb指令集n nint(*mmap)(structfile*,structvm_area_struct*);int(*mmap)(structfile*,structvm_area_struct*);n nmmapmmap用来请求将设备内存映射到进程的地址空间用来请求将设备内存映射到进程的地址空间用来请求将设备

102、内存映射到进程的地址空间用来请求将设备内存映射到进程的地址空间. .如果这如果这如果这如果这个方法是个方法是个方法是个方法是NULL,mmapNULL,mmap系统调用返回系统调用返回系统调用返回系统调用返回ENODEVENODEVn nint(*open)(int(*open)(structinode*,structinode*,structfile*);structfile*);n n该操作用来打开设备文件,也是对设备文件进行的第一个操该操作用来打开设备文件,也是对设备文件进行的第一个操该操作用来打开设备文件,也是对设备文件进行的第一个操该操作用来打开设备文件,也是对设备文件进行的第一个操

103、作作作作, ,如果这个操作为空如果这个操作为空如果这个操作为空如果这个操作为空, ,设备打开一直成功设备打开一直成功设备打开一直成功设备打开一直成功, ,但是你的驱动程但是你的驱动程但是你的驱动程但是你的驱动程序不会被调用序不会被调用序不会被调用序不会被调用49TM49ARM及Thumb指令集n nint(*flush)(structfile*);int(*flush)(structfile*);n nflushflush操作在进程关闭它的设备文件描述符的拷贝时调用操作在进程关闭它的设备文件描述符的拷贝时调用操作在进程关闭它的设备文件描述符的拷贝时调用操作在进程关闭它的设备文件描述符的拷贝时调

104、用; ;它它它它应当执行应当执行应当执行应当执行( (并且等待并且等待并且等待并且等待) )设备的任何未完成的操作设备的任何未完成的操作设备的任何未完成的操作设备的任何未完成的操作. .当前当前当前当前,flush,flush在在在在很少驱动中使用很少驱动中使用很少驱动中使用很少驱动中使用. .如果如果如果如果flushflush为为为为NULL,NULL,内核简单地忽略用户内核简单地忽略用户内核简单地忽略用户内核简单地忽略用户应用程序的请求应用程序的请求应用程序的请求应用程序的请求. .n nint(*release)(structinode*,structfile*);int(*relea

105、se)(structinode*,structfile*);n n在文件结构被释放时引用这个操作在文件结构被释放时引用这个操作在文件结构被释放时引用这个操作在文件结构被释放时引用这个操作. .如同如同如同如同open,releaseopen,release可以可以可以可以为为为为NULL.NULL.n nint(*fsync)(structfile*,structdentry*,int);int(*fsync)(structfile*,structdentry*,int);n n这个方法是这个方法是这个方法是这个方法是fsyncfsync系统调用的后端系统调用的后端系统调用的后端系统调用的后端

106、, ,用户调用来刷新任何挂着用户调用来刷新任何挂着用户调用来刷新任何挂着用户调用来刷新任何挂着的数据的数据的数据的数据. .如果这个指针是如果这个指针是如果这个指针是如果这个指针是NULL,NULL,系统调用返回系统调用返回系统调用返回系统调用返回EINVAL.EINVAL.50TM50ARM及Thumb指令集n nint(*aio_fsync)(structkiocb*,int);int(*aio_fsync)(structkiocb*,int);n n这是这是这是这是fsyncfsync方法的异步版本方法的异步版本方法的异步版本方法的异步版本n nint(*fasync)(int,stru

107、ctfile*,int);int(*fasync)(int,structfile*,int);n n这个操作用来通知设备它的这个操作用来通知设备它的这个操作用来通知设备它的这个操作用来通知设备它的FASYNCFASYNC标志的改变标志的改变标志的改变标志的改变. .异步通知异步通知异步通知异步通知是一个高级的主题是一个高级的主题是一个高级的主题是一个高级的主题, ,在第在第在第在第66章中描述章中描述章中描述章中描述. .这个成员可以是这个成员可以是这个成员可以是这个成员可以是NULLNULL如果驱动不支持异步通知如果驱动不支持异步通知如果驱动不支持异步通知如果驱动不支持异步通知. .n ni

108、nt(*lock)(structfile*,int,structfile_lock*);int(*lock)(structfile*,int,structfile_lock*);n nlocklock方法用来实现文件加锁方法用来实现文件加锁方法用来实现文件加锁方法用来实现文件加锁; ;加锁对常规文件是必不可少的加锁对常规文件是必不可少的加锁对常规文件是必不可少的加锁对常规文件是必不可少的特性特性特性特性, ,但是设备驱动几乎从不实现它但是设备驱动几乎从不实现它但是设备驱动几乎从不实现它但是设备驱动几乎从不实现它. .51TM51ARM及Thumb指令集n nssize_t(*readv)(st

109、ructfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);n nssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);n n该操作用来对一个包含多个内存区的单个读或写操作该操作用来对一个包含多个内存区

110、的单个读或写操作该操作用来对一个包含多个内存区的单个读或写操作该操作用来对一个包含多个内存区的单个读或写操作; ;这些系统调用允这些系统调用允这些系统调用允这些系统调用允许它们这样做而不必对数据进行额外拷贝许它们这样做而不必对数据进行额外拷贝许它们这样做而不必对数据进行额外拷贝许它们这样做而不必对数据进行额外拷贝. .如果这些函数指针为如果这些函数指针为如果这些函数指针为如果这些函数指针为NULL,NULL,readread和和和和writewrite方法被调用方法被调用方法被调用方法被调用( (可能多于一次可能多于一次可能多于一次可能多于一次).).n nssize_t(*sendfile)

111、(structfile*,loff_t*,size_t,read_actor_t,void*);ssize_t(*sendfile)(structfile*,loff_t*,size_t,read_actor_t,void*);n n这个方法实现这个方法实现这个方法实现这个方法实现sendfilesendfile系统调用的读系统调用的读系统调用的读系统调用的读, ,使用最少的拷贝从一个文件描述符使用最少的拷贝从一个文件描述符使用最少的拷贝从一个文件描述符使用最少的拷贝从一个文件描述符搬移数据到另一个搬移数据到另一个搬移数据到另一个搬移数据到另一个. .例如例如例如例如, ,它被一个需要发送文件

112、内容到一个网络连接的它被一个需要发送文件内容到一个网络连接的它被一个需要发送文件内容到一个网络连接的它被一个需要发送文件内容到一个网络连接的 webweb服务器使用服务器使用服务器使用服务器使用. .设备驱动常常使设备驱动常常使设备驱动常常使设备驱动常常使sendfilesendfile为为为为NULL.NULL.n nssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);n nse

113、ndpagesendpage是是是是sendfilesendfile的另一半的另一半的另一半的另一半; ;它由内核调用来发送数据它由内核调用来发送数据它由内核调用来发送数据它由内核调用来发送数据, ,一次一页一次一页一次一页一次一页, ,到对到对到对到对应的文件应的文件应的文件应的文件. .设备驱动实际上不实现设备驱动实际上不实现设备驱动实际上不实现设备驱动实际上不实现sendpage.sendpage.52TM52ARM及Thumb指令集n nunsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong(*get

114、_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);unsignedlong,unsignedlong,unsignedlong);n n这个方法的目的是在进程的地址空间找一个合适的位置来映射在底层设这个方法的目的是在进程的地址空间找一个合适的位置来映射在底层设这个方法的目的是在进程的地址空间找一个合适的位置来映射在底层设这个方法的目的是在进程的地址空间找一个合适的位置来映射在底层设备上的内存段中备上的内存段中备上的内存段中备上的内存段中. .这个任务通常由内存管理代码进行这个任务通常

115、由内存管理代码进行这个任务通常由内存管理代码进行这个任务通常由内存管理代码进行; ;这个方法存在为了这个方法存在为了这个方法存在为了这个方法存在为了使驱动能强制特殊设备可能有的任何的对齐请求使驱动能强制特殊设备可能有的任何的对齐请求使驱动能强制特殊设备可能有的任何的对齐请求使驱动能强制特殊设备可能有的任何的对齐请求. .大部分驱动可以置这个大部分驱动可以置这个大部分驱动可以置这个大部分驱动可以置这个方法为方法为方法为方法为NULL.NULL.n nint(*check_flags)(int)int(*check_flags)(int)n n这个方法允许模块检查传递给这个方法允许模块检查传递给这

116、个方法允许模块检查传递给这个方法允许模块检查传递给fnctl(F_SETFL.)fnctl(F_SETFL.)调用的标志调用的标志调用的标志调用的标志. .n nint(*dir_notify)(structfile*,unsignedlong);int(*dir_notify)(structfile*,unsignedlong);53TM53ARM及Thumb指令集2 2 inodeinode数据结构数据结构n ninodeinode译成中文就是译成中文就是译成中文就是译成中文就是索引节点索引节点索引节点索引节点。每个存储设备或存储设备的分。每个存储设备或存储设备的分。每个存储设备或存储设备

117、的分。每个存储设备或存储设备的分区(存储设备是硬盘、软盘、区(存储设备是硬盘、软盘、区(存储设备是硬盘、软盘、区(存储设备是硬盘、软盘、U U盘盘盘盘.)被格式化为文件系统)被格式化为文件系统)被格式化为文件系统)被格式化为文件系统后,应该有两部份,后,应该有两部份,后,应该有两部份,后,应该有两部份,一部份是一部份是一部份是一部份是inodeinode,另一部份是,另一部份是,另一部份是,另一部份是BlockBlock,BlockBlock是用来存储数据用的。而是用来存储数据用的。而是用来存储数据用的。而是用来存储数据用的。而inodeinode呢,就是用来存储这些数呢,就是用来存储这些数呢

118、,就是用来存储这些数呢,就是用来存储这些数据的信息据的信息据的信息据的信息,这些信息包括,这些信息包括,这些信息包括,这些信息包括文件大小、属主、归属的用户组、读文件大小、属主、归属的用户组、读文件大小、属主、归属的用户组、读文件大小、属主、归属的用户组、读写权限等。写权限等。写权限等。写权限等。n ninodeinode为每个文件进行信息索引为每个文件进行信息索引为每个文件进行信息索引为每个文件进行信息索引,所以就有了,所以就有了,所以就有了,所以就有了inodeinode的数值。操的数值。操的数值。操的数值。操作系统根据指令,能通过作系统根据指令,能通过作系统根据指令,能通过作系统根据指令

119、,能通过inodeinode值最快的找到相对应的文件值最快的找到相对应的文件值最快的找到相对应的文件值最快的找到相对应的文件。n n 做个比喻,比如一本书,存储设备或分区就相当于这本书,做个比喻,比如一本书,存储设备或分区就相当于这本书,做个比喻,比如一本书,存储设备或分区就相当于这本书,做个比喻,比如一本书,存储设备或分区就相当于这本书,BlockBlock相当于书中的每一页,相当于书中的每一页,相当于书中的每一页,相当于书中的每一页,inodeinode就相当于这本书前面的目录就相当于这本书前面的目录就相当于这本书前面的目录就相当于这本书前面的目录,一本书有很多的内容,如果想查找某部份的内

120、容,我们可以,一本书有很多的内容,如果想查找某部份的内容,我们可以,一本书有很多的内容,如果想查找某部份的内容,我们可以,一本书有很多的内容,如果想查找某部份的内容,我们可以先查目录,通过目录能最快的找到我们想要看的内容。虽然不先查目录,通过目录能最快的找到我们想要看的内容。虽然不先查目录,通过目录能最快的找到我们想要看的内容。虽然不先查目录,通过目录能最快的找到我们想要看的内容。虽然不太恰当,但还是比较形象。太恰当,但还是比较形象。太恰当,但还是比较形象。太恰当,但还是比较形象。54TM54ARM及Thumb指令集n n当我们用当我们用当我们用当我们用lsls查看某个目录或文件时,如果加上查

121、看某个目录或文件时,如果加上查看某个目录或文件时,如果加上查看某个目录或文件时,如果加上ii参数,就可参数,就可参数,就可参数,就可以看到以看到以看到以看到inodeinode节点了;比如节点了;比如节点了;比如节点了;比如 比如比如比如比如hello.chello.chello.chello.c文件的文件的文件的文件的inodeinodeinodeinode值为值为值为值为44467644467644467644467655TM55ARM及Thumb指令集2 2 inodeinode数据结构数据结构p222p222n n文文文文件件件件系系系系统统统统处处处处理理理理的的的的文文文文件件件件

122、所所所所需需需需要要要要的的的的信信信信息息息息在在在在inodeinode(索索索索引引引引结结结结点点点点)数数数数据据据据结结结结构构构构中中中中。InodeInode数数数数据结构提供了关于特殊设备文件据结构提供了关于特殊设备文件据结构提供了关于特殊设备文件据结构提供了关于特殊设备文件/dev/DriverName/dev/DriverName的信息,定义如下的信息,定义如下的信息,定义如下的信息,定义如下:n nstructinodestructinode称做索引节点数据结构,称做索引节点数据结构,称做索引节点数据结构,称做索引节点数据结构,inodeinode(索引结点)数据结构定

123、义如下:(索引结点)数据结构定义如下:(索引结点)数据结构定义如下:(索引结点)数据结构定义如下:n nstructinodestructinoden nstructhlist_nodei_hash;structhlist_nodei_hash;n nstructlist_headi_list;structlist_headi_list;n nstructlist_headi_sb_list;structlist_headi_sb_list;n nstructlist_headi_dentry;structlist_headi_dentry;n nunsignedlongi_ino;unsig

124、nedlongi_ino;n natomic_ti_count;atomic_ti_count;n numode_ti_mode;umode_ti_mode;n n.56TM56ARM及Thumb指令集n nInodeInode结构包含了大量有关文件的信息结构包含了大量有关文件的信息结构包含了大量有关文件的信息结构包含了大量有关文件的信息, ,但通常情况下对设备但通常情况下对设备但通常情况下对设备但通常情况下对设备驱动开发比较有用的成员有下面两个驱动开发比较有用的成员有下面两个驱动开发比较有用的成员有下面两个驱动开发比较有用的成员有下面两个n ndev_tdev_ti_rdev;/i_rdev

125、;/该成员包含了设备编号该成员包含了设备编号该成员包含了设备编号该成员包含了设备编号n nstructcdevstructcdev*i_cdev;/*i_cdev;/指向字符设备文件的指针指向字符设备文件的指针指向字符设备文件的指针指向字符设备文件的指针n n说明说明说明说明: :当当当当inodeinode指向一个字符设备文件时指向一个字符设备文件时指向一个字符设备文件时指向一个字符设备文件时, ,该成员包含了指向该成员包含了指向该成员包含了指向该成员包含了指向structcdevstructcdev 结构的指针结构的指针结构的指针结构的指针, ,其中其中其中其中cdevcdev结构是字符设

126、备结构体结构是字符设备结构体结构是字符设备结构体结构是字符设备结构体57TM57ARM及Thumb指令集cdev结构结构n n在在在在Linux2.6Linux2.6内核中一个字符设备用内核中一个字符设备用内核中一个字符设备用内核中一个字符设备用cdevcdev结构来描述,其定义结构来描述,其定义结构来描述,其定义结构来描述,其定义如下:如下:如下:如下:n nstructcdevstructcdevn nstructkobjectkobj;structkobjectkobj;n nstructmodule*owner;/structmodule*owner;/所属模块所属模块所属模块所属模块

127、n nconststructfile_operations*ops;/conststructfile_operations*ops;/文件操作结构文件操作结构文件操作结构文件操作结构 n nstructlist_headlist;structlist_headlist;n ndev_tdev;/dev_tdev;/设备号设备号设备号设备号n nunsignedintcount;unsignedintcount;n n; ;58TM58ARM及Thumb指令集3 file数据结构数据结构n n设备驱动程序中设备驱动程序中设备驱动程序中设备驱动程序中, ,另一个非常重要的数据结构就是另一个非常重要

128、的数据结构就是另一个非常重要的数据结构就是另一个非常重要的数据结构就是FileFile结构结构结构结构, ,它它它它不同于应用程序空间的不同于应用程序空间的不同于应用程序空间的不同于应用程序空间的FILEFILE指针指针指针指针,FILE,FILE指针定义在指针定义在指针定义在指针定义在C C库中因库中因库中因库中因而不会出现在内核代码中而不会出现在内核代码中而不会出现在内核代码中而不会出现在内核代码中, ,而而而而sturctfilesturctfile只出现在内核代码中只出现在内核代码中只出现在内核代码中只出现在内核代码中, ,从不出现在用户程序中从不出现在用户程序中从不出现在用户程序中从

129、不出现在用户程序中n n内核用内核用内核用内核用inodeinode结构表示具体的文件结构表示具体的文件结构表示具体的文件结构表示具体的文件, ,而而而而filefile结构表示打开的文件结构表示打开的文件结构表示打开的文件结构表示打开的文件描述符描述符描述符描述符n n对于对于对于对于单个文件单个文件单个文件单个文件, ,可能会有可能会有可能会有可能会有许多个许多个许多个许多个表示打开的文件描述符表示打开的文件描述符表示打开的文件描述符表示打开的文件描述符filefile结结结结构构构构, ,但是它们都指向了单个的但是它们都指向了单个的但是它们都指向了单个的但是它们都指向了单个的inodei

130、node结构结构结构结构, ,所以所以所以所以filefile结构和结构和结构和结构和inodeinode结构是不同的结构是不同的结构是不同的结构是不同的. .59TM59ARM及Thumb指令集n n3 3filefile数据结构数据结构数据结构数据结构 n nstructfilestructfilen nstructlist_headstructlist_headf_list;/f_list;/打开的文件形成一个列表打开的文件形成一个列表打开的文件形成一个列表打开的文件形成一个列表 n nstructdentrystructdentry*f_dentry;/*f_dentry;/指向相关目

131、录项的指针指向相关目录项的指针指向相关目录项的指针指向相关目录项的指针n nstructvfsmount*f_vfsmnt;/structvfsmount*f_vfsmnt;/执行执行执行执行VFSVFS挂载点的指针挂载点的指针挂载点的指针挂载点的指针n nstructfile_operationsstructfile_operations*f_op;/*f_op;/执行文件操作的指针执行文件操作的指针执行文件操作的指针执行文件操作的指针n natomic_tatomic_tf_count;/f_count;/使用该结构的进程数使用该结构的进程数使用该结构的进程数使用该结构的进程数n nuns

132、ignedintunsignedintf_flags;/f_flags;/文件打开的标志,如读写等文件打开的标志,如读写等文件打开的标志,如读写等文件打开的标志,如读写等n nmode_tmode_tf_mode;/f_mode;/文件打开的模式文件打开的模式文件打开的模式文件打开的模式3 file数据结构数据结构60TM60ARM及Thumb指令集n nloff_tloff_tf_pos;/f_pos;/文件的当前位置文件的当前位置文件的当前位置文件的当前位置n nunsignedunsignedlonglongf_reada,f_reada,f_ramax,f_ramax,f_raend,

133、f_raend,f_ralen,f_ralen,f_rawin;f_rawin;/*/*预预预预读读读读标标标标志志志志、要要要要预预预预读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数读的最多页面数、上次预读后的文件指针、预读的字节数以及预读的页面数*/*/n nstructfown_structstructfown_structf_owner;/f_owner;/文件的所有者文件的所有者文件的所有者文件的所有者n nunsignedintun

134、signedintf_uid,f_gid;/f_uid,f_gid;/用户的用户的用户的用户的UIDUID和和和和GIDGIDn nintintf_error;/f_error;/网络写操作错误码网络写操作错误码网络写操作错误码网络写操作错误码n nunsignedlongunsignedlongf_version;/f_version;/版本号版本号版本号版本号n nvoidvoid*private_data;/tty*private_data;/tty驱动程序使用驱动程序使用驱动程序使用驱动程序使用n nstructkiobufstructkiobuf*f_iobuf;*f_iobuf;n

135、 nlonglongf_iobuf_lock;f_iobuf_lock;n n; ;61TM61ARM及Thumb指令集7.2.2字符设备驱动开发字符设备驱动开发p228n n7.2.27.2.2设备驱动程序的开发流程设备驱动程序的开发流程设备驱动程序的开发流程设备驱动程序的开发流程 n n(1 1)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口电路。电路。电路。电路。n n(2 2)设计所要实现的文件操作,定义设计所要实现的文件操作,

136、定义设计所要实现的文件操作,定义设计所要实现的文件操作,定义file_operationsfile_operations结构。结构。结构。结构。n n(3 3)实现所需的文件操作调用,如)实现所需的文件操作调用,如)实现所需的文件操作调用,如)实现所需的文件操作调用,如readread、writewrite等。等。等。等。n n(2 2)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数_init,_init,其中定义设备号。其中定义设备号。其中定义设备号。其中定义设备号。n n(3 3)实现初始化函数)实现初始化函数)实现初始化函数)实现初始化函数, ,其中实现驱

137、动的注册。其中实现驱动的注册。其中实现驱动的注册。其中实现驱动的注册。n n(6 6)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用request_irqrequest_irq向内核注册。向内核注册。向内核注册。向内核注册。n n(7 7)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数_exit,_exit,完成驱动的注销完成驱动的注销完成驱动的注销完成驱动的注销, ,释放设备号释放设备号释放设备号释放设备号n n(7 7)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核

138、中,或者用insmodinsmod命令加载模块。命令加载模块。命令加载模块。命令加载模块。n n(8 8)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。62TM62ARM及Thumb指令集定义定义file_operations结构结构p228n n在在在在simplesimple设备驱动程序中它的设备驱动程序中它的设备驱动程序中它的设备驱动程序中它的file_operationsfile_operations结构是如下初结构是如下初结构是如下初结构是如

139、下初始化的始化的始化的始化的: :n nstructfile_operationsstructfile_operationssimple_fopssimple_fops=n n.owner=THIS_MODULE,.owner=THIS_MODULE,n n.llseek=simple_llseek,.llseek=simple_llseek,n n.read=simple_read,.read=simple_read,n n.write=simple_write,.write=simple_write,n n.ioctl=simple_ioctl,.ioctl=simple_ioctl,n

140、n.open=simple_open,.open=simple_open,n n.release=simple_release,;.release=simple_release,; 对对对对simple_fopssimple_fops变量进变量进变量进变量进行初始化行初始化行初始化行初始化 将对应操作的将对应操作的将对应操作的将对应操作的函数名函数名函数名函数名作为作为作为作为指针指针指针指针传递给相应传递给相应传递给相应传递给相应的成员的成员的成员的成员63TM63ARM及Thumb指令集7.2.2字符设备驱动开发字符设备驱动开发p228n n7.2.27.2.2设备驱动程序的开发流程设备驱

141、动程序的开发流程设备驱动程序的开发流程设备驱动程序的开发流程 n n(1 1)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口电路。电路。电路。电路。n n(2 2)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义file_operationsfile_operations结构。结构。结构。结构。n n(3 3)实现所需的文件操作调用,如实现所需的文件操作调用,如实现所

142、需的文件操作调用,如实现所需的文件操作调用,如openopen、readread、writewrite等。等。等。等。n n(2 2)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数_init,_init,其中定义设备号。其中定义设备号。其中定义设备号。其中定义设备号。n n(3 3)实现初始化函数)实现初始化函数)实现初始化函数)实现初始化函数, ,其中实现驱动的注册。其中实现驱动的注册。其中实现驱动的注册。其中实现驱动的注册。n n(6 6)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用request_irqrequest_ir

143、q向内核注册。向内核注册。向内核注册。向内核注册。n n(7 7)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数_exit,_exit,完成驱动的注销完成驱动的注销完成驱动的注销完成驱动的注销, ,释放设备号释放设备号释放设备号释放设备号n n(7 7)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用insmodinsmod命令加载模块。命令加载模块。命令加载模块。命令加载模块。n n(8 8)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试

144、该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。64TM64ARM及Thumb指令集实现所需的文件操作调用实现所需的文件操作调用p228n nstaticintdevice_open(structinode*inode,structfile*file)staticintdevice_open(structinode*inode,structfile*file) printk(“simpledeviceisopenn”);/printk(“simpledeviceisopenn”);/打印一句话打印一句话打印一句话打印一句话try_module_gett

145、ry_module_get(THIS_MODULE);(THIS_MODULE);n nn nreturn0;return0; n n函数:函数:函数:函数:try_module_get()try_module_get()n n如果模块已经插入内核,则递增该模块引用计数,每次加如果模块已经插入内核,则递增该模块引用计数,每次加如果模块已经插入内核,则递增该模块引用计数,每次加如果模块已经插入内核,则递增该模块引用计数,每次加1 1;如果该模块还没有插入内核,则返回;如果该模块还没有插入内核,则返回;如果该模块还没有插入内核,则返回;如果该模块还没有插入内核,则返回0 0表示出错。表示出错。表示

146、出错。表示出错。65TM65ARM及Thumb指令集实现所需的文件操作调用实现所需的文件操作调用n nstaticintdevice_release(structinode*inode,structfile*file)staticintdevice_release(structinode*inode,structfile*file) printk(“Simpledevice_releasecalln);printk(“Simpledevice_releasecalln);module_put(THIS_MODULE);module_put(THIS_MODULE);n nn nreturn0;

147、return0; n n函数:函数:函数:函数:module_put()module_put()n n与与与与try_module_get()try_module_get()相对应,相对应,相对应,相对应,该模块引用计数减该模块引用计数减该模块引用计数减该模块引用计数减1 1;如果该;如果该;如果该;如果该模块还没有插入内核,则返回模块还没有插入内核,则返回模块还没有插入内核,则返回模块还没有插入内核,则返回0 0表示出错表示出错表示出错表示出错66TM66ARM及Thumb指令集7.2.2字符设备驱动开发字符设备驱动开发n n7.2.27.2.2设备驱动程序的开发流程设备驱动程序的开发流程设

148、备驱动程序的开发流程设备驱动程序的开发流程 n n(1 1)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口电路。电路。电路。电路。n n(2 2)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义file_operationsfile_operations结构。结构。结构。结构。n n(3 3)实现所需的文件操作调用,如)实现所需的文件操作调用,如)实现所需的文件操作调

149、用,如)实现所需的文件操作调用,如readread、writewrite等。等。等。等。n n(2 2)实现初始化模块函数实现初始化模块函数实现初始化模块函数实现初始化模块函数_init,_init,其中定义设备号。其中定义设备号。其中定义设备号。其中定义设备号。n n(3 3)实现初始化函数)实现初始化函数)实现初始化函数)实现初始化函数, ,其中实现驱动的注册。其中实现驱动的注册。其中实现驱动的注册。其中实现驱动的注册。n n(6 6)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用request_irqrequest_irq向内核注册。向内核注册。向内核注册

150、。向内核注册。n n(7 7)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数)实现卸载模块函数_exit,_exit,完成驱动的注销完成驱动的注销完成驱动的注销完成驱动的注销, ,释放设备号释放设备号释放设备号释放设备号n n(7 7)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用insmodinsmod命令加载模块。命令加载模块。命令加载模块。命令加载模块。n n(8 8)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行

151、测试。)测试该设备,编写应用程序,对驱动程序进行测试。67TM67ARM及Thumb指令集1)1)设备主设备号的添加和注销设备主设备号的添加和注销p225p225n n设备驱动在加载时首先需要调用入口函数设备驱动在加载时首先需要调用入口函数设备驱动在加载时首先需要调用入口函数设备驱动在加载时首先需要调用入口函数module_init()module_init(),该,该,该,该函数完成设备驱动的函数完成设备驱动的函数完成设备驱动的函数完成设备驱动的初始化工作初始化工作初始化工作初始化工作,比如分配设备号,比如分配设备号,比如分配设备号,比如分配设备号, ,驱动程序驱动程序驱动程序驱动程序的注册

152、的注册的注册的注册, ,寄存器置位、结构体赋值等。寄存器置位、结构体赋值等。寄存器置位、结构体赋值等。寄存器置位、结构体赋值等。68TM68ARM及Thumb指令集1)1)设备主设备号的添加和注销设备主设备号的添加和注销p226p226n n建立字符设备以前,建立字符设备以前,建立字符设备以前,建立字符设备以前,必须分配设备号必须分配设备号必须分配设备号必须分配设备号。可以使用。可以使用。可以使用。可以使用register_chrdev_regionregister_chrdev_region函数完成,该函数原型如下:函数完成,该函数原型如下:函数完成,该函数原型如下:函数完成,该函数原型如下

153、:n nintregister_chrdev_region(dev_tintregister_chrdev_region(dev_tfirstfirst,unsignedint,unsignedintcountcount, ,charchar*name*name) )n nFirst:First:是要分配的设备号范围的起始值是要分配的设备号范围的起始值是要分配的设备号范围的起始值是要分配的设备号范围的起始值n nCount:Count:是请求的连续设备号的数目是请求的连续设备号的数目是请求的连续设备号的数目是请求的连续设备号的数目n nName:Name:是与该编号范围关联的设备名称,也就是在

154、是与该编号范围关联的设备名称,也就是在是与该编号范围关联的设备名称,也就是在是与该编号范围关联的设备名称,也就是在/proc/devices/proc/devices和和和和sysfhsysfh中出现的名称。中出现的名称。中出现的名称。中出现的名称。n n如何能够确定起始范围如何能够确定起始范围如何能够确定起始范围如何能够确定起始范围? ?69TM69ARM及Thumb指令集n n实际上,实际上,实际上,实际上,LinuxLinux提供了提供了提供了提供了动态分配设备号的函数动态分配设备号的函数动态分配设备号的函数动态分配设备号的函数,通过这个函,通过这个函,通过这个函,通过这个函数,内核可以

155、为我们分配合适的设备号。函数原型如下:数,内核可以为我们分配合适的设备号。函数原型如下:数,内核可以为我们分配合适的设备号。函数原型如下:数,内核可以为我们分配合适的设备号。函数原型如下:n nintalloc_chrdev_regionintalloc_chrdev_region( (dev_t*devdev_t*dev,unsignedintfirsetminor,unsignedintfirsetminor,unsignedintcount,char*name)unsignedintcount,char*name)n n该函数的返回值为该函数的返回值为该函数的返回值为该函数的返回值为0,

156、0,表示不能获得设备号表示不能获得设备号表示不能获得设备号表示不能获得设备号n ndev:dev:用于输出的参数用于输出的参数用于输出的参数用于输出的参数,保存已分配范围的第一个编号。,保存已分配范围的第一个编号。,保存已分配范围的第一个编号。,保存已分配范围的第一个编号。n nFirstminorFirstminor: :是要使用的被请求的第一个是要使用的被请求的第一个是要使用的被请求的第一个是要使用的被请求的第一个次设备号次设备号次设备号次设备号,通常设置,通常设置,通常设置,通常设置为为为为0 0。n nCount:Count:是请求的连续设备号的数目是请求的连续设备号的数目是请求的连续

157、设备号的数目是请求的连续设备号的数目n nName:Name:是与该编号范围关联的设备名称是与该编号范围关联的设备名称是与该编号范围关联的设备名称是与该编号范围关联的设备名称70TM70ARM及Thumb指令集动态分配设备号动态分配设备号n n例如例如例如例如: :n n#defineCDRIVER_NAME“simple_chrev”#defineCDRIVER_NAME“simple_chrev”n ndev_tdev_tsimple_dev;simple_dev;n nintresult,count=1,CDRIVER_MAJOR=0,CDRIVER_MINOR=0;intresult,

158、count=1,CDRIVER_MAJOR=0,CDRIVER_MINOR=0;n nresultresult= =alloc_chrdev_region(alloc_chrdev_region(&simple_dev&simple_dev,CDRIVER_MINOR,count,CDRIVER_MINOR,count,CDRIVER_NAMECDRIVER_NAME) )n nCDRIVER_MAJOR=CDRIVER_MAJOR=MAJORMAJOR(simple_dev);(simple_dev);n nIf(result0)If(resultops=&simple_fops;simpl

159、e_cdevops=&simple_fops;n nsimple_cdevowner=THISMODULE;simple_cdevowner=THISMODULE;78TM78ARM及Thumb指令集linux2.6驱动的注册和卸载驱动的注册和卸载p226n n(4)(4)利用函数利用函数利用函数利用函数cdev_add()cdev_add()来注册设备来注册设备来注册设备来注册设备n n函数定义函数定义函数定义函数定义:int:intcdev_addcdev_add(structcdev*dev,(structcdev*dev,dev_tdev_tnum,num,unsignedintuns

160、ignedintcount);count);n n若该函数返回若该函数返回若该函数返回若该函数返回0, 0,表示设备注册成功表示设备注册成功表示设备注册成功表示设备注册成功, ,非非非非0 0注册失败注册失败注册失败注册失败n n例如例如例如例如: :n nif(cdev_add(simple_cdev,simple_dev,count)if(cdev_add(simple_cdev,simple_dev,count)n nprintk(KERN_NOTICE“somethingwrongwhenadd!”)printk(KERN_NOTICE“somethingwrongwhenadd!”)

161、n n n nElseElsen nprintk(“successaddingsimple_cdev”)printk(“successaddingsimple_cdev”)n n 79TM79ARM及Thumb指令集7.2.2字符设备驱动开发字符设备驱动开发n n7.2.27.2.2设备驱动程序的开发流程设备驱动程序的开发流程设备驱动程序的开发流程设备驱动程序的开发流程 n n(1 1)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口)硬件接口设计或使用嵌入式处理器的生产商提供参考接口电路

162、。电路。电路。电路。n n(2 2)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义)设计所要实现的文件操作,定义file_operationsfile_operations结构。结构。结构。结构。n n(3 3)实现所需的文件操作调用,如)实现所需的文件操作调用,如)实现所需的文件操作调用,如)实现所需的文件操作调用,如readread、writewrite等。等。等。等。n n(2 2)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数)实现初始化模块函数_init,_init,其中定义设备号。其中定义设备号。其中定义设备号。其中定义设备号。

163、n n(3 3)实现初始化函数)实现初始化函数)实现初始化函数)实现初始化函数, ,其中实现设备驱动的注册。其中实现设备驱动的注册。其中实现设备驱动的注册。其中实现设备驱动的注册。n n(6 6)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用)实现中断服务,并用request_irqrequest_irq向内核注册。向内核注册。向内核注册。向内核注册。n n(7 7)实现卸载模块函数实现卸载模块函数实现卸载模块函数实现卸载模块函数_exit,_exit,完成驱动的注销完成驱动的注销完成驱动的注销完成驱动的注销, ,释放设备号释放设备号释放设备号释放设备号n n(7 7)编译该驱动程

164、序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用)编译该驱动程序到内核中,或者用insmodinsmod命令加载模块。命令加载模块。命令加载模块。命令加载模块。n n(8 8)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。)测试该设备,编写应用程序,对驱动程序进行测试。80TM80ARM及Thumb指令集linux2.6驱动的注册和卸载驱动的注册和卸载n n对字符设备驱动程序的卸载有对字符设备驱动程序的卸载有对字符设备驱动程序的卸载有对字符设备驱动程序的卸载有1 1

165、个步骤个步骤个步骤个步骤: :n n函数定义函数定义函数定义函数定义:voidcdev_del(structcdev*);/:voidcdev_del(structcdev*);/n n作用作用作用作用: :注销设备,通常发生在驱动模块的卸载函数中注销设备,通常发生在驱动模块的卸载函数中注销设备,通常发生在驱动模块的卸载函数中注销设备,通常发生在驱动模块的卸载函数中n nstaticvoidstaticvoid_exit_exit simple_exit(void)simple_exit(void)n n n ncdev_del(cdev_del(simple_devsimple_dev);/

166、);/注销设备注销设备注销设备注销设备n nunregister_chrdev_region(unregister_chrdev_region(simple_devsimple_dev,count)/,count)/释放设备号释放设备号释放设备号释放设备号n n 81TM81ARM及Thumb指令集n n自此,一个驱动程序的框架已经基本完成了,见书自此,一个驱动程序的框架已经基本完成了,见书自此,一个驱动程序的框架已经基本完成了,见书自此,一个驱动程序的框架已经基本完成了,见书p227p227页页页页n n下面就可以编写下面就可以编写下面就可以编写下面就可以编写makefilemakefile

167、文件,加载模块测试了!文件,加载模块测试了!文件,加载模块测试了!文件,加载模块测试了!n n但是这个模块没有任何实际的意义,我们要做的事情就是在但是这个模块没有任何实际的意义,我们要做的事情就是在但是这个模块没有任何实际的意义,我们要做的事情就是在但是这个模块没有任何实际的意义,我们要做的事情就是在此基础上将其充实和完善。此基础上将其充实和完善。此基础上将其充实和完善。此基础上将其充实和完善。n n包括:包括:包括:包括:n n7.2.2.47.2.2.4内存操作内存操作内存操作内存操作n n7.2.2.57.2.2.5中断中断中断中断n n7.2.2.6I/O7.2.2.6I/O操作操作操作操作n n7.2.2.77.2.2.7延时与定时器延时与定时器延时与定时器延时与定时器

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号