LINUX 设备驱动概述.ppt

上传人:wj 文档编号:9417587 上传时间:2023-05-18 格式:PPT 页数:41 大小:644KB
下载 相关 举报
LINUX 设备驱动概述.ppt_第1页
第1页 / 共41页
LINUX 设备驱动概述.ppt_第2页
第2页 / 共41页
LINUX 设备驱动概述.ppt_第3页
第3页 / 共41页
LINUX 设备驱动概述.ppt_第4页
第4页 / 共41页
LINUX 设备驱动概述.ppt_第5页
第5页 / 共41页
LINUX 设备驱动概述.ppt_第6页
第6页 / 共41页
LINUX 设备驱动概述.ppt_第7页
第7页 / 共41页
LINUX 设备驱动概述.ppt_第8页
第8页 / 共41页
LINUX 设备驱动概述.ppt_第9页
第9页 / 共41页
LINUX 设备驱动概述.ppt_第10页
第10页 / 共41页
LINUX 设备驱动概述.ppt_第11页
第11页 / 共41页
LINUX 设备驱动概述.ppt_第12页
第12页 / 共41页
LINUX 设备驱动概述.ppt_第13页
第13页 / 共41页
LINUX 设备驱动概述.ppt_第14页
第14页 / 共41页
LINUX 设备驱动概述.ppt_第15页
第15页 / 共41页
LINUX 设备驱动概述.ppt_第16页
第16页 / 共41页
LINUX 设备驱动概述.ppt_第17页
第17页 / 共41页
LINUX 设备驱动概述.ppt_第18页
第18页 / 共41页
LINUX 设备驱动概述.ppt_第19页
第19页 / 共41页
LINUX 设备驱动概述.ppt_第20页
第20页 / 共41页
亲,该文档总共41页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

LINUX 设备驱动概述.ppt

《LINUX 设备驱动概述.ppt》由会员分享,可在线阅读,更多相关《LINUX 设备驱动概述.ppt(41页珍藏版)》请在冰点文库上搜索。

LINUX 设备驱动概述.ppt

,LINUX设备驱动概述,内容摘要,设备驱动程序概述设备驱动程序的一般接口添加设备驱动程序的一般方法设备驱动程序的加载与使用,设备驱动程序基本概念-软件系统流程,设备驱动程序概述,设备驱动程序基本概念-驱动程序作用,设备驱动程序将复杂的硬件抽象成一个结构良好的设备,并通过提供统一的程序接口为系统的其它部分提供使用设备的能力和方法。

设备驱动程序(应该只是)为系统的其它部分提供各种使用设备的能力,使用设备的方法应该由应用程序决定。

设备驱动程序概述,Linux下对外设的访问只能通过驱动程序Linux对于驱动程序有统一的接口,以文件的形式定义系统的驱动程序:

Open、Release、read、write、ioctl驱动程序是内核的一部分,可以使用中断、DMA等操作驱动程序需要在用户态和内核态之间传递数据,设备驱动程序基本概念,设备驱动程序概述,设备驱动程序基本概念,驱动程序与应用程序的区别1、应用程序以main函数开始,驱动程序则没用main函数。

它以特殊的模块初始化函数为入口。

2、应用程序从头至尾执行一个任务,驱动程序在完成初始化后,等待系统调用。

3、应用程序可以使用GLIBC等标准C函数库,驱动程序不能使用标准C函数库。

设备驱动程序概述,设备驱动程序的分类,字符设备驱动程序各种串行接口,并行接口等。

块设备驱动程序磁盘设备等网络设备驱动程序网卡等。

杂项设备驱动程序不属于上述三种设备之外的一些设备,如SCSI,时钟等。

设备驱动程序概述,驱动程序在操作系统中的位置,设备驱动程序是内核代码的一部分。

驱动程序的地址空间是内核的地址空间。

驱动程序的代码直接对设备硬件(实际是设备的各种寄存器)进行控制(实际就是读写操作)。

应用程序通过操作系统的系统调用执行相应的驱动程序函数。

中断则直接执行相应的中断程序代码。

设备驱动程序的file_operations结构体的地址被注册到内核中的设备链表中。

块设备和字符设备以设备文件的方式建立在文件系统中的/dev目录下,而且每个设备都有一个主设备号和一个次设备号。

设备驱动程序概述,驱动程序在操作系统中的位置,设备驱动程序概述,主设备号和次设备号,主设备号标识设备对应的驱动程序一个驱动程序可以控制若干个设备,次设备号提供了一种区分它们的方法系统增加一个驱动程序就要赋予它一个主设备号。

这一赋值过程在驱动程序的初始化过程中intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);,设备驱动程序概述,主设备号和次设备号,在/dev目录下使用ll命令(ls-l)可以查看各个设备的设备类型、主从设备号等,设备驱动程序概述,创建设备节点,设备已经注册到内核表中,对于设备的访问通过设备文件(设备文件与设备驱动程序的主设备号匹配),内核会调用驱动程序中的正确函数给程序一个它们可以请求设备驱动程序的名字。

这个名字必须插入到/dev目录中,并与驱动程序的主设备号和次设备号相连使用mknod在文件系统上创建一个设备节点mknoddev_namedriver_typemajorminor,设备驱动程序概述,创建设备节点,设备驱动程序概述,动态分配设备号,在Documentation/device.txt文件中可以找到已经静态分配给大部分设备的列表由于许多数字已经分配了,为新设备选择一个唯一的号码是很困难的.如果调用alloc_chrdev_region函数,内核会动态为设备分配一个可用的设备编号intalloc_chrdev_region(dev_t*dev,unsignedintfirstminor,unsignedintcount,char*name);,设备驱动程序概述,动态分配的问题,动态分配的主设备号不能保证总是一样的,无法事先创建设备节点可以从/proc/devices读取cat/proc/devices利用脚本动态创建设备文件节点,设备驱动程序概述,设备管理的问题,如今,Linux支持很多不同种类的硬件。

这意味着/dev中都有数百个特殊文件来表示所有这些设备。

而且,这些特殊文件中大多数甚至不会映射到系统中存在的设备上,设备驱动程序概述,使用devfs,在Linux2.4的内核里引入了devfs来解决linux下设备文件管理的问题在驱动程序中通过devfs_register()函数创建设备文件系统的节点系统启动的时候mount设备文件系统所有需要的设备节点都由内核自动管理。

/dev目录下只有挂载的设备,设备驱动程序概述,Linux2.6内核与udev,Linux2.6内核引入了sysfs文件系统为每个系统的硬件树进行分级处理Devfs在Linux2.6中被标记为舍弃的特性(在Linux2.6.15及以后的版本则取消了对它的支持),而使用udev。

维护动态设备从sysfs获得的信息,可以提供对特定设备的固定设备名。

对于热插拔的设备,这尤其重要udev是在用户空间的脚本文件,这很容易被编辑和修改可以和hotplug脚本配合使用为了保证旧应用程序的兼容性,在嵌入式系统中,是用devfs还是一个好方法。

即使在Linux2.6.15内核以后,也可以通过ndevfs(nanodevfs)补丁提供对devfs特性的兼容。

设备驱动程序概述,在Linux2.6内核中使用udev,建议,在2.6.15以后的版本中使用udev使用ramfs作为udev的载体mounttramfsnone/devudev使用的规则集位于/etc/udev/*udev的官方地址:

http:

/www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html参考文章:

Writingudevrules,设备驱动程序概述,设备的注册,Linux内核针对不同类型的设备提供了不同的设备注册方法和相关函数。

只有向内核注册成功的设备,才可以使用内核资源正确驱动硬件设备。

Linux内核使用区分的设备链表来维护不同的设备驱动程序。

字符设备的注册内核在内部使用类型structcdev的结构来代表字符设备,使用cdev_alloc()函数来为该结构分配空间。

structcdev*my_cdev=cdev_alloc();,设备驱动程序概述,设备的注册,初始化cdev结构设备voidcdev_init(structcdev*cdev,structfile_operations*fops);向内核添加cdev结构设备intcdev_add(structcdev*dev,dev_tnum,unsignedintcount);从内核去除cdev结构设备voidcdev_del(structcdev*dev);,设备驱动程序概述,设备驱动程序的接口,通常所说的设备驱动程序接口是指结构file_operations,它定义在include/linux/fs.h中。

structfile_operationsstructmodule*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);,设备驱动程序的一般接口,file_operations结构体,主要包括:

open,close(或者release),read,write,ioctl,poll,mmap等结构体file_operations定义的结构体变量将作为一个参数在注册一个设备驱动程序时传递给内核。

内核使用设备链表维护各种注册的设备。

不同类型的设备使用不同的链表。

设备驱动程序的一般接口,file_operations结构体,structfile_operationsdemo_fops=完成了将驱动函数映射为标准接口。

例如:

staticstructfile_operationsdemo_fops=owner:

THIS_MODULE,write:

demo_write,read:

demo_read,ioctl:

demo_ioctl,open:

demo_open,release:

demo_release,;上面的这种特殊表示方法不是标准C的语法,这是GNU编译器的一种特殊扩展,它使用名字对进行结构字段的初始化,它的好处体现在结构清晰,易于理解,并且避免了结构发生变化带来的许多问题。

设备驱动程序的一般接口,设备驱动程序的接口,Open接口:

int(*open)(structinode*inode,structfile*filp);open方法提供给驱动来做任何的初始化来准备后续的操作.在大部分驱动中,open应当进行下面的工作:

检查特定设备错误。

如果设备是首次打开,则对其进行初始化。

识别次设备号,如有必要修改f_op指针。

分配并填写filp-private_data中的数据。

设备驱动程序的一般接口,设备驱动程序的接口,设备驱动程序的一般接口,Release接口:

intscull_release(structinode*inode,structfile*filp)与open方法相反,release方法应完成如下功能:

释放由open分配的filp-private_data中的所有内容在最后一次关闭操作时关闭设备,设备驱动程序的接口,Read和Write接口:

ssize_tread(structfile*filp,char_user*buff,size_tcount,loff_t*offp);ssize_twrite(structfile*filp,constchar_user*buff,size_tcount,loff_t*offp);read方法完成将数据从内核拷贝到应用程序空间,write方法相反,将数据从应用程序空间拷贝到内核。

由于用户空间和内核空间的内存映射方式完全不同,所以不能使用象memcpy之类的函数,必须使用如下函数:

unsignedlongcopy_to_user(void*to,constvoid*from,unsignedlongcount);unsignedlongcopy_from_user(void*to,constvoid*from,unsignedlongcount);,设备驱动程序的一般接口,设备驱动程序的接口,ioctl接口:

ioctl方法主要用于对设备进行读写之外的其他控制,比如配置设备、进入或退出某种操作模式,这些操作一般都无法通过read/write文件操作来完成int(*ioctl)(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg),设备驱动程序的一般接口,注册中断函数,intrequest_irq(unsignedintirq,irqreturn_t(*handler)(int,void*,structpt_regs*),unsignedlongirq_flags,constchar*devname,void*dev_id)irq,中断向量号handler,中断处理函数irq_flags,中断标志:

SA_SHIRQ、SA_INTERRUPT、SA_SAMPLE_RANDOMdevname,设备名dev_id,设备id,可以为NULL。

共享中断必须区分。

设备驱动程序的一般接口,注册的中断处理函数handler,系统所注册的中断处理子程序,中断产生时由系统来调用。

原型为:

irqreturn_t(*handler)(intirq,void*dev_id,structpt_regs*regs)irq,中断号dev_id,申请时告诉系统的设备标识regs,中断发生时寄存器内容返回值在include/linux/interrupts中定义为typedefintirqreturn_t。

非零表示中断有效,设备驱动程序的一般接口,释放中断,卸载驱动程序时,需要注销相应的中断处理程序,并释放中断。

voidfree_irq(unsignedintirq,void*dev_id),设备驱动程序的一般接口,linux驱动调试,Printk函数printk函数中可以使用附加不同的日志级别或消息优先级运行时打印级别cat/proc/sys/kernel/printk上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别。

设备驱动程序的一般接口,编译设备驱动程序,静态内核模块(添加驱动代码至内核源码树中)在内核源代码目录的相应子目录下建立设备驱动程序目录。

在设备驱动程序目录下建立Makefile文件。

修改上一级目录的Makefile文件。

动态内核模块(单独的驱动代码目录)内核模块需要使用内核的头文件,因此需要安装内核源代码,2.6版本内核需要对内核源码进行编译。

编写Makefile。

添加设备驱动程序的一般方法,配置和编译脚本-kbuild,把驱动程序放到内核中,在编译内核的时候可以自由裁减。

kbuild脚本随着Linux内核的发展,更新很快参考Documentation/kbuild目录下的相关文档,添加设备驱动程序的一般方法,配置和编译脚本-Makefile,Linux内核的编译过程,是通过内核源码中根目录和各个子目录中的Makefile分级管理的。

其中,根目录的Makefile是最重要的,它可以看成是Makefile最初的入口。

Make脚本读取.config文件,并根据其信息最终生成vmlinux(elf格式的Linux内核)和modules(模块)。

make通过向下递归调用子目录中的Makefile来编译这两个目标。

添加设备驱动程序的一般方法,版本依赖,驱动模块是紧密结合到一个特殊内核版本的数据结构和函数原型上的。

如果改变当前驱动模块针对的内核版本,需要重新编译驱动模块。

驱动模块建立过程的其中一步是对当前内核树中的文件(称为vermagic.o)连接进行检测;其中的内容含有相当多的有关要为其建立模块的内核的信息,包括目标内核版本,编译器版本,以及许多重要配置变量的设置。

添加设备驱动程序的一般方法,设备驱动模块的加载,设备驱动程序被静态编译到内核中的情况:

module_init()宏是内核在启动过程中运行设备的初始化函数,驱动程序的加载随内核的启动一起完成。

静态编译的内核模块不能被动态卸载,只有到系统关闭时由内核执行相应的卸载函数,如module_exit()。

设备驱动程序被动态加载到内核中的情况:

首先,驱动程序需要被编译成目标文件,如demo.o或demo.ko。

在操作系统运行之后,使用insmod命令将驱动程序模块动态加载到内核中$insmoddemo.ko使用insmod命令动态加载的内核模块可以使用rmmod命令动态地从内核中卸载$rmmoddemo.ko使用内核的动态模块加载/卸载功能需要内核支持kmod功能。

设备驱动程序的加载与使用,设备驱动程序的使用方法,应用层使用open、close、read、write系统调用需要编写应用程序使用系统命令可以进行最基本的测试:

cat/dev/urandomecho/dev/urandom/dev/fb0ddif=/dev/touchscreenof=/var/tmp/testbs=16count=100,设备驱动程序的加载与使用,设备驱动程序的使用方法,设备驱动程序的加载与使用,Helloworld模块,#include#includeMODULE_LICENSE(DualBSD/GPL);staticinthello_init(void)printk(KERN_ALERTHello,worldn);return0;staticvoidhello_exit(void)printk(KERN_ALERTGoodbye,cruelworldn);module_init(hello_init);module_exit(hello_exit);,设备驱动程序的加载与使用,讨论时间,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2