第十章嵌入式Linux设备驱动程序

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

1嵌入式系统第十章嵌入式Linux设备驱动程序2第十章Agenda10.1Linux的设备介绍10.2Linux设备驱动程序介绍10.3Linux的设备驱动程序的模块结构10.4Linux的设备驱动程序的编写举例310.1Linux的设备介绍10.1.1Linux的设备分类10.1.2设备文件10.1.3设备号410.1.1Linux的设备分类Linux支持三类硬件设备:字符设备:指那些无须缓冲直接读写的设备块设备:只能以块为单位进行读写,典型的块大小为512或1024字节。网络设备:可以通过BSD套接口访问510.1.2设备文件Linux抽象了对硬件的处理,所有的硬件设备都可以作为普通文件来看待;它们可以使用和操作系统相同的、标准的系统调用接口来打开、关闭、读写和控制I/O的操作,而驱动程序的主要任务也就是要实现这些系统调用函数。6设备文件Linux系统中的所有硬件设备都使用一个特殊的设备文件来表示例如,系统中的第一个IDE硬盘用/dev/had来表示。串口可以用/dev/stty0来表示.由于引入了设备文件这一概念,Linux为文件和设备提供了一致的用户接口。对用户来说,设备文件与普通文件并无区别。710.1.3设备号每个设备文件都对应有两个设备号:一个是主设备号,表示该设备的种类,也标识了该设备所使用的驱动程序;另一个是次设备号,标识使用同一设备驱动程序的不同硬件设备。使用mknod命令可以创建指定类型的设备文件,同时为其分配相应的主设备号和次设备号。[root@xsbaseroot]#mknod/dev/lp0c608第十章Agenda10.1Linux的设备介绍10.2Linux设备驱动程序介绍10.3Linux的设备驱动程序的模块结构10.4Linux的设备驱动程序的编写举例910.2Linux设备驱动程序介绍10.2.1设备驱动的层次10.2.2设备驱动程序与外界的接口10设备驱动程序设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序主要完成以下功能:对设备初始化和释放。把数据从内核传送到硬件和从硬件读取数据。读取应用程序传送给设备文件的数据和回送应用程序请求的数据。检测和处理设备出现的错误。1110.2.1设备驱动的层次Linux下的设备驱动程序是内核的一部分,运行在内核模式,也就是说设备驱动程序为内核提供了一个I/O接口,用户使用这个接口实现对设备的操作。Linux的设备驱动程序介于(设备)文件系统与物理设备中间。用户通过应用程序进程输入输入请求,进而调用(设备)文件系统,(设备)文件系统通过设备驱动程序控制物理设备进行设备的操作,如进行磁盘文件的读出和写入操作等等,如图所示。Linux设备驱动程序包含了中断处理程序和设备服务子程序。12设备驱动的层次用户程序的进程(设备)文件系统设备驱动程序设备服务子程序中断处理程序物理设备物理设备控制器输入/输出请求输入/输出响应1310.2.2设备驱动程序与外界的接口打开的设备在内核内部由file结构标识,内核使用file_operations结构访问驱动程序的函数。file_operations结构是一个定义在linux/fs.h中的函数指针数组,这就是通常所说的设备驱动程序与外界的接口。每个文件都与它自己的函数集相关联(通过包括指向file_operations结构的一个名为f_op的指针字段)。这些操作主要负责系统调用的实现,并因此被命名为open、read等。14file_operationsstructfile_operations{structmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);int(*readdir)(structfile*,void*,filldir_t);unsignedint(*poll)(structfile*,structpoll_table_struct*);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*flush)(structfile*);int(*release)(structinode*,structfile*);int(*fsync)(structfile*,structdentry*,intdatasync);int(*fasync)(int,structfile*,int);int(*lock)(structfile*,int,structfile_lock*);ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);#ifdefMAGIC_ROM_PTRint(*romptr)(structfile*,structvm_area_struct*);#endif/*MAGIC_ROM_PTR*/};15Ownermodule的拥有者。Llseek重新定位读写位置。Read从设备中读取数据。Write向字符设备中写入数据。Readdir只用于文件系统,对设备无用。Ioctl控制设备,除读写操作外的其他控制命令。Mmap将设备内存映射到进程地址空间,通常只用于块设备。Open打开设备并初始化设备。Flush清除内容,一般只用于网络文件系统中。Release关闭设备并释放资源。Fsync实现内存与设备的同步,如将内存数据写入硬盘。Fasync实现内存与设备之间的异步通讯。Lock文件锁定,用于文件共享时的互斥访问。Readv在进行读操作前要验证地址是否可读。Writev在进行写操作前要验证地址是否可写。16第十章Agenda10.1Linux的设备介绍10.2Linux设备驱动程序介绍10.3Linux的设备驱动程序的模块结构10.4Linux的设备驱动程序的编写举例1710.3Linux的设备驱动程序的模块结构Linux中的可加载模块(loadablemodule)是Linux内核支持的动态可加载模块(dynamicloadablemodule),它们是内核的一部分,但是并没有编译到内核里面去。模块可以单独编译成目标代码,以.o的目标文件形式存在。它可以根据需要在系统启动后动态加载到系统内核之中。当模块不再被需要时,可以动态地写在出系统内核。Linux中地大多数设备驱动程序都以模块地形式存在。18模块模块的装载和卸载有两种方式:可以通过超级用户运行insmod和rmmod命令显式地将模块载入内核或从内核中卸载;内核自身也可以在需要时,请求守护进程(kerneld)装载和卸载模块。模块方式对性能的影响:采用了一些额外的代码和数据结构,它们占用了一部分内存。用户进程通过模块对内核资源进行的访问是间接的,不可避免地降低了内核资源地访问效率。19常用命令lsmod:列出当前系统中加载的模块。insmod,modprobe:用于加载当前模块,但insmod不会自动解决依存关系,而modprobe则可以根据模块间依存关系以及/etc/modules/conf文件中的内容自动插入模块。rmmod:把某个不再使用的模块从内核中卸载。depmod:制造模块相关文件(moduledependencyfile),以便后面要使用insmod命令用来查询模块的具体位置20第十章Agenda10.1Linux的设备介绍10.2Linux设备驱动程序介绍10.3Linux的设备驱动程序的模块结构10.4Linux的设备驱动程序的编写举例21字符设备驱动程序一个最简单的字符设备驱动程序该字符设备具备4个基本操作bytedevice_open(),bytedevice_write(),bytedevice_read(),bytedevice_release()实现的基本功能为向这个新建的字符设备先写入一些数据,然后再从这个设备中读取这些数据。221主要数据结构和全局变量file_operations{}Structbytedevice.c232主要接口函数bytedevice_open,bytedevice_release:主要是对设备进行初始化和释放,实现了设备的打开和关闭功能。bytedevice_read:当设备文件执行该函数调用时,表面上看像时从设备中读取数据,实际上是从内核空间的数据队列中读取,通过copy_to_user()函数,把数据从内核空间传送到用户空间,使得用户空间的其他代码(测试代码)可以访问这些数据。bytedevice_write:和bytedevice_read()函数相似,只不过数据传送的方向发生了变化,即把参数中的count字节数从用户空间的缓冲区buf复制到硬件或者内核的缓冲区中。243模块加载采取模块加载的方式:init_module和cleanup_module函数主要使用了驱动程序的注册与注销中的register_chrdev()和unregister_chrdev()。254驱动安装过程完成上面的工作后,对前面的代码进行编译,并通过insmod的方式加载其到内核中。比如bytedevice源代码放在/usr/src/bytedevice下,可以这样编译,生成bytedevice.o文件:$gccbytedevice.c–I/usr/src/bytedevice/include–cbytedevice.c–D__KERNEL__-DMODULE接下来把目标文件加载到内核。可以使用命令:$insmod–fbytedevice.o如果已经成功安装,在/proc/devices文件中就可以找到设备bytedevice,并且可以看到它的主设备号(内核动态分配所得)。如果要卸载模块,运行:$rmmodbytedevice创建一个设备文件,通过设备文件就可以访问驱动程序2610.4Linux的设备驱动程序的编写举例作业在Linux系统上编写/编译/加载/使用这个驱动程序27EndofChapter10

1 / 27
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功