第9章linux驱动程序设计

上传人:今*** 文档编号:106671718 上传时间:2019-10-15 格式:PPT 页数:84 大小:1.42MB
返回 下载 相关 举报
第9章linux驱动程序设计_第1页
第1页 / 共84页
第9章linux驱动程序设计_第2页
第2页 / 共84页
第9章linux驱动程序设计_第3页
第3页 / 共84页
第9章linux驱动程序设计_第4页
第4页 / 共84页
第9章linux驱动程序设计_第5页
第5页 / 共84页
点击查看更多>>
资源描述

《第9章linux驱动程序设计》由会员分享,可在线阅读,更多相关《第9章linux驱动程序设计(84页珍藏版)》请在金锄头文库上搜索。

1、,第9章 Linux驱动程序设计,目 录,9.1 Linux 设备驱动程序 9.2 Linux经典Hello world驱动程序 9.3 Linux字符设备驱动程序实例,9.1 Linux 设备驱动程序,Linux内核模块,Linux操作系统的内核是单一体系结构(monolithic kernel) 有了模块机制后,提高Linux操作系统的可扩充性,内核编程不再是一个恶梦 什么是模块呢? 模块的全称是“动态可加载内核模块”(Loadable Kernel Module,LKM) 模块在内核空间运行 模块实际上是一种目标对象文件 没有链接,不能独立运行,但是其代码可以在运行时链接到系统中作为内核

2、的一部分运行或从内核中取下,从而可以动态扩充内核的功能 这种目标代码通常由一组函数和数据结构组成,Linux内核模块的优点与缺点,优点 使得内核更加紧凑和灵活 修改内核时,不必全部重新编译整个内核。系统如果需要使用新模块,只要编译相应的模块,然后使用insmod将模块装载即可 模块的目标代码一旦被链接到内核,它的作用域和静态链接的内核目标代码完全等价 缺点 由于内核所占用的内存是不会被换出的,所以链接进内核的模块会给整个系统带来一定的性能和内存利用方面的损失; 装入内核的模块就成为内核的一部分,可以修改内核中的其他部分,因此,模块的使用不当会导致系统崩溃; 为了让内核模块能访问所有内核资源,内

3、核必须维护符号表,并在装入和卸载模块时修改符号表; 模块会要求利用其它模块的功能,所以,内核要维护模块之间的依赖性.,Linux内核模块与应用程序的区别,C语言程序 Linux内核模块 运行 用户空间 内核空间 入口 main() module_init()指定; 出口 无 module_exit()指定; 编译 gcc c Makefile 连接 ld insmod 运行 直接运行 insmod 调试 gdb kdbug, kdb, kgdb等,9.1.1 Linux设备分类,Linux系统的设备分为字符设备(char device)、块设备(block device)和网络设备(netwo

4、rk device)三种。,(1)字符设备,字符设备是指存取时没有缓存的设备。典型的字符设备包括鼠标,键盘,串行口等。 字符设备在I/O传输过程中以字符为单位的,但是不一定是以字节为单位,因为一个字符展16bit(2个字节)。它是通过文件系统节点来存储,在Linux系统中,字符设备以特别的文件方式在文件目录树中占据位置并拥有自己的结点,并且指明了文件类型,但是,操作(包括打开、关闭、读、写操作)起来却和普通文件一样。大部分字符设备仅仅是数据通道,只能顺序存取。,当字符设备与主机连接后,可以使用mknod命令来为设备创建字符特别文件。例如,为名为/dev/kui的主机创建字符特别文件的命令如下:

5、 mknod /dev/kui c 4 9 其中:4是设主设备号;9是次设备为9;c是字符型类型标记。,字符设备和主机的通信一般采用中断方式,当字符设备上的数据传输完成时,就通过总线向系统发出中断处理信号,数据传输的底层控制由中断处理程序和设备驱动程序协同完成。,2)块设备,块设备主要包括硬盘软盘设备、CD-ROM等。块设备的读写都有缓存来支持,并且块设备必须能够随机存取(random access),字符设备则没有这个要求。 块设备和字符设备也有相似之处,块设备通过位于 /dev 目录的文件系统结点来存取,其读写操作跟字符设备一样,可以一次传送任意数目的字节。,块设备和字符设备的区别在于:,

6、1)内核在内部管理数据的方式不同,块设备将信息存储在固定大小的块中,每个块都有自己的地址,数据块的大小通常在51232768字节之间,并且每个块之间都能独立进行读写操作。 2)内核/驱动的软件接口完全不同。在大多数的UNIX操作系统中,块设备只支持以块为单位的访问方式。Linux支持以字符方式来访问块设备,在/dev目录中的块设备,均以字符设备的外观出现。所以,字符设备和块设备的区别主要体现在内核中的管理方式,操作方式和内核/设备驱动接口上。,(3)网络设备,网络设备是一个连接在多个主机之间,并能够相互交换数据的设备。它不一定是硬件设备,也可能是一个纯粹的软件设备。 网络设备在Linux里做专

7、门的处理。Linux的网络系统主要是基于BSD unix的socket机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递。系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。,网络设备驱动程序异步地接收来自外部世界的网络数据包,通过push操作将进来的数据包压向内核,而块设备驱动程序则将一片数据缓冲发送给内核,驱动程序将相应设备的特征信息登记到内核中特定的数据结构中。 块设备驱动程序可以使用文件形式来描述,而网络驱动程序则不可以使用一般的文件读写操作调用,网络设备驱动程序有自己的内存名字空间,使用push等操作来完成数据包的转换与递送。,内核

8、中有专门为网络设备驱动程序设计的数据包操作接口,如图9-1所示。路由就是通过网络接口sn0到达网络snullnet0的意思,使用route add -net snullnet0 dev sn0指令来完成,Linux 2.2版本以上内核就不用这样做,内核将自动添加。,远程,9.1.2 Linux驱动程序的模块化,Linux中大部分的驱动程序都以模块的形式编写,这些驱动程序源码可以修改到内核中,也可以把他们编译成模块形式,在需要的时候动态加载。例如,在块驱动设备中,当系统试图读取这个设备(即调用read()时),就会运行驱动程序中的block_read() 这个函数。,常用的管理模块命令如下:,(

9、1)查看模块信息命令。可以用lsmod、cat /proc/modules、modinfo三个命令查看模块信息 (2)modprobe命令的功能是自动处理可载入模块。 语法:modprobe -acdlrtvV-help模块文件符号名称 = 符号值,(3)insmod(install module)挂载模块 。 功能说明:载入模块。 语法:insmod -fkmpsvxX-o 模块文件符号名称 = 符号值,(4)rmmod 移除已挂载模块。 (5)depmod 创建模块依赖关系的列表。这个模块管理工具是创建模块依赖关系的列表,有几个参数需要注意一下,目前的Linux 2.6x版本,是自动解决依

10、赖关系,9.1.3 Linux设备驱动程序结构,Linux设备驱动程序及用户程序、操作系统内容之间的关系及结构如图9-2所示。其中Linux的设备驱动程序大致可以分为:驱动程序注册、设备打开、设备读写操作、设备控制操作、设备中断和轮询处理、设备释放、驱动程序注销等七个部分。,(1)驱动程序注册,向系统增加一个驱动程序意味着要赋予它一个主设备号,这可以通过在驱动程序的初始化过程中调用register_chrdev()或者register_blkdev()来完成。,(2)设备的打开,打开设备是通过调用file_operations结构中的函数open()来完成的,它是驱动程序用来为今后的操作完成初

11、始化准备工作的。在大部分驱动程序中,open()通常需要完成下列工作:,检查设备相关错误,如设备未准备就绪等。 如果是第一次打开,则初始化硬件设备。 识别次设备号,如果有必要则更新读写操作的当前位置指针f_ops。 分配和填写要放在file-private_data里的数据结构。 使用计数器增加1。,(3)设备的读写操作,字符设备的读写操作相对比较简单,直接使用函数read()和write()就可以了。但如果是块设备,则需要调用函数block_read()和block_write()来进行数据读写,这两个函数将向设备请求表中增加读写请求,以便Linux内核可以对请求顺序进行优化处理,由于内核操

12、作是对内存缓冲区而不是直接对设备本身,因此能很大程度上加快读写速度。如果内存缓冲区中没有所要读入的数据,或者需要执行写操作将数据写入设备,那么就要执行真正的数据传输,这是通过调用数据结构blk_dev_struct中的函数request_fn()来完成的。,(4)设备的控制操作,除了读写操作外,应用程序有时还需要对设备进行控制,这时可以通过设备驱动程序中的函数ioctl()来完成,ioctl()的用法与具体设备密切关联,因此需要根据设备的实际情况进行具体分析。,(5)设备的中断和轮询处理,对于不支持中断的硬件设备,读写时需要轮流查询设备状态,以便决定是否继续进行数据传输。如果设备支持中断,则可

13、以按中断方式进行操作。 通过Linux提供的系统调用函数(例如init_module等)进入内核,这些函数在2.6内核版本下总共有两百多个,提供了几乎所有应用程序进入内核所需要执行的操作。,系统的内核函数都有“sys_”前缀(例如函数sys_init_module()),应用程序通过访问设备文件系统来调用这些函数。这一层主要是“devfs”(device filesystem())文件管理机制,它是从普通文件和设备文件抽象出来的一个文件系统层,完成进入具体的设备文件操作之前的准备工作。,(6)设备释放,释放设备是通过调用file_operations结构中的函数release()来完成的,这个

14、设备方法有时也被称为close(),它的作用正好与open()相反,通常要完成下列工作:,使用计数器减1。 释放在file-private_data中分配的内存。 如果计数器为0,则关闭设备。,(7)驱动程序注销,向系统增加一个驱动程序意味着要赋予它一个主设备号,这可以通过在驱动程序的初始化过程中调用register_chrdev()或者register_blkdev()来完成。而在关闭字符设备或者块设备时,则需要通过调用unregister_chrdev()或unregister_blkdev()从内核中注销设备,同时释放占用的主设备号。,9.1.4 Linux驱动程序常用的数据结构,(1)

15、file结构。file结构是设备驱动程序一个重要的数据结构,指示当前系统中已打开的文件。它在C语言库中定义,在调用内核open函数时创建,并传递给在该设备上进行操作的所有函数,直到最后的close()函数执行完毕。file结构中还包含了指向它所拥有的file_operations结构的指针。 file代表一个打开的文件,在执行file_operations中的open操作时被创建,这里需要注意的是与用户空间inode指针的区别,一个在内核;而file指针在用户空间,由C库来定义。,(2)inode结构,inode结构由内核自动生成,代表已打开文件的描述符,与每个打开的文件一一对应。inode被

16、内核用来代表一个文件,注意和struct file的区别在于:struct inode一个是代表文件,而struct file一个是代表打开的文件。,struct inode包括很重要的两个成员:,dev_t i_rdev 设备文件的设备号 struct cdev *i_cdev 代表字符设备的数据结构 dev_t扩展到32位,其中12位主设备号,20位从设备号;而cdev用于存储一个指向字符设备文件的指针。 inode结构是用来在内核内部表示文件的,同一个文件可以被多次打开,所以可以对应很多file结构,但是只对应一个inode结构。,(3)file_operations结构,在Linux内核下使用file_operations数据结构,来建立设备驱动程序中的函数与主设备号(major number)之间的对应关系。该数据结构中包含了指向驱动程序内部大多数函数的指针,描述了虚拟文

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

最新文档


当前位置:首页 > 高等教育 > 大学课件

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