LINUX-内核驱动设计入门.ppt

上传人:小飞机 文档编号:5575616 上传时间:2023-07-29 格式:PPT 页数:37 大小:308.50KB
返回 下载 相关 举报
LINUX-内核驱动设计入门.ppt_第1页
第1页 / 共37页
LINUX-内核驱动设计入门.ppt_第2页
第2页 / 共37页
LINUX-内核驱动设计入门.ppt_第3页
第3页 / 共37页
LINUX-内核驱动设计入门.ppt_第4页
第4页 / 共37页
LINUX-内核驱动设计入门.ppt_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《LINUX-内核驱动设计入门.ppt》由会员分享,可在线阅读,更多相关《LINUX-内核驱动设计入门.ppt(37页珍藏版)》请在三一办公上搜索。

1、第 十 章 内核驱动设计入门,嵌入式系统及其软件工具,本章提要,10.1 驱动程序概述,设备驱动程序是操作系统内核和机器硬件之间的接口。所有对设备的操作都必须由被控设备相关的代码驱动程序来完成。设备驱动隐藏了设备的具体细节,为不同设备提供了统一的访问接口。用户或者应用程序可以像操作普通文件一样对硬件设备进行操作,设备驱动是内核的一部分。,10.1.1 设备驱动功能,设备的初始化和释放 负责内核与外设之间的数据交换 提供各类设备服务 检测和处理设备工作过程中出现的错误,驱动程序在嵌入式Linux中的作用:,在嵌入式系统中,要访问某个特定的硬件,实际上就是访问物理的地址空间(处理器内的寄存器、外设

2、的地址映像)。然而,由于MMU的内存映射以及对操作系统的保护,运行在用户态的应用程序一般不能够直接访问硬件地址,因此需要驱动程序作为应用程序和访问硬件之间的媒介。某些驱动程序并不能直接给应用程序调用,而是给Linux内核调用。例如:串口作为console的物理载体;或者驱动程序由操作系统调用,应用程序可以间接的使用驱动程序,如framebuffer,网络设备驱动等。(要去哦球驱动程序必须按照某个框架编写,供上层模块使用),10.1.2 驱动程序开发注意,开发驱动程序和开发应用程序不同;驱动程序应提供尽量多的选项给用户,不应该强加约束;尽量提高驱动程序的速度、效率,尽量简化,便于维护。,10.2

3、 Linux设备与设备驱动,Linux把设备分成3类,每类设备有自己的接口和常用框架,他们也有很多共性。,字符设备:采用字符流方式访问的设备,每次只传输一个字符。特点:顺序访问。鼠标、键盘、串口等。块设备:采用随机访问的方式访问,数据具有固定大小的块的设备;(Linux中块设备与字符设备使用基本一致)特点:缓冲存储,随机访问。硬盘、光盘等。网络设备:采用数据包传输方式访问的设备。特点:与字符设备和块设备不同,没有设备文件。通过socket进行使用。,设备,设备的分类,10.2.1 Linux设备和设备驱动,设备驱动的共性:设备驱动工作在内核态,误操作后果很严重;设备驱动必须提供一个标准的内核接

4、口,字符和块设备采用文件接口,网络设备采用套接字;驱动可以采用标准的内核服务,如:“内存分配”、等待队列、中断机制等;驱动可以动态的连接到内核中,不用时可以卸载。也可将驱动编译到内核中。,10.2.1 Linux设备和设备驱动,10.2.2 Linux设备文件,bash#ls-l/dev 查看相关设备信息crw-1 root root 14,3Jan30 2003 dspcrw-rw-1 root floppy 2,0Jan30 2003 fd0,系统启动时会把设备文件系统挂载在/dev目录下,linux的设备文件的创建、删除和目录层次等都由各设备驱动程序管理。/dev中每个文件都动态的对应了

5、一个系统上存在的设备驱动程序。,10.2.3 Linux对设备文件的操作,open()int open(const*pathname,int flag);open函数用于通过文件路径打开一个文件,返回一个整数类型的文件描述符。,close()int close(int fd);close函数用于关闭文件,close会让数据写回磁盘,并释放文件所占用的资源。,10.2.3 Linux对设备文件的操作,read()ssize_t read(int fd,void*buf,size_t count);read函数从fd指向的文件传送count个字节到buf指针指向的内存中文件读写指针的位置会随着读取

6、到的字节移动。当读取成功时,最好将返回值和count值进行比较若返回的值比count少,则可能读到了文件尾,或者read操作被中断了等。,10.2.4 设备驱动程序接口,write()ssize_t write(int fd,void*buf,size_t count);write函数把参数buf指向的内存写入count个字节到fd指向的文件内。文件的读写位置也会随之变化;,10.2.3 Linux对设备文件的操作,lseek()loff_t lseek(int fd,loff_t offset,int whence);lseek函数用来控制文件的读写位置。,ioctl()int ioctl(

7、int fd,unsigned int cmd,);ioctl是Linux中对设备文件操作的特殊函数。可以对应到驱动程序的相应函数中。,文件操作示例:,#include#include#include#include int main()int fd,size;char s=”File Operationn”;char buffer80;fd=open(“/tmp/tempfile”,O_WRONLY|O_CREAT);write(fd,s,sizeof(s);close(fd);fd=open(“/tmp/tempfile”,O_RDONLY);size=read(fd,buffer,siz

8、eof(buffer);close(fd);printf(“Display:%s”,buffer);return 0;,以上的程序首先打开文件,接下来向文件中写入内容,然后从文件中读取内容,最后关闭文件。其运行结果为:Display:File operation,10.2.4 Linux对设备文件的操作,设备驱动程序是操作系统内核和机器硬件之间的接口。所有对设备的操作都必须由被控设备相关的代码驱动程序来完成。设备驱动隐藏了设备的具体细节,为不同设备提供了统一的访问接口。,应用程序与驱动程序之间的调用关系,10.2.4 Linux对设备文件的操作,Linux应用程序中,通过对文件操作的函数对驱动

9、程序的设备文件进行调用。,10.2.4 Linux对设备文件的操作,struct file_operations/文件操作struct module*owner;loff_t(*llseek)(struct file*,loff_t,int);ssize_t(*read)(struct file*,char*,size_t,loff_t*);ssize_t(*write)(struct file*,const char*,size_t,loff_t*);int(*readdir)(struct file*,void*,filldir_t);unsigned int(*poll)(struct

10、file*,struct poll_table_struct*);int(*ioctl)(struct inode*,struct file*,unsigned int,long);int(*mmap)(struct file*,struct vm_area_struct*);int(*open)(struct inode*,struct file*);int(*release)(struct inode*,struct file*);,字符设备操作,10.2.4 Linux对设备文件的操作,struct block_device_operations/块设备操作int(*open)(stru

11、ct inode*,struct file*);int(*release)(struct inode*,struct file*);int(*ioctl)(struct inode*,struct file*,unsigned int,long);int(*check_media_change)(kdev_t);int(*revalidate_disk)(kdev_t);struct module*owner;,Linux2.4定义的块设备操作,10.2.4 Linux对设备文件的操作,struct block_device_operations int(*open)(struct inode

12、*,struct file*);int(*release)(struct inode*,struct file*);int(*ioctl)(struct inode*,struct file*,unsigned int,long);int(*compat_ioctl)(struct file*,unsigned int,long);int(*media_changed)(struct gendisk*);int(*revalidate_disk)(struct gendisk*);struct module*owner;,Linux2.6定义的块设备操作,10.2.5 内核空间和用户空间交互,

13、int access_ok(int type,unsigned long addr,unsigned long size);unsigned long copy_to_user(void*to,const void*from,unsigned long fen);unsigned long copy_from_user(void*to,const void*from,unsigned long fen);void*mmap(void*start,size_t length,int prot,int flags,int fd,loff_t offsize);,直接编译到内核,再运行新的内核来调试

14、调试效率低,10.2.6 Linux驱动开发和调试方法,module模式,将单独的驱动编译为module模式,单独加载调试 调试效率高,调试时不用重启内核,10.2.7 内核模块module,1.什么是module?module就是一个程序,但他可以被动态加载到kernel里,成为kernel的一部分。加载到kernel里的module具有和kernel一样的权力,它可以访问kernel里发布的任何数据结构,使用发布的function()。,10.2.7 内核模块module,2.kernel如何管理module?,10.2.7 内核模块module,3.module的初始化与回收,int i

15、nit_module(void)/模块初始化函数 int result;result=register_chrdev(“参数1”,“参数2”,“参数3”);if(result0)printk(DEVICE_NAME“cant get major mumber”);return result;if(device_major=0)device_major=result;return result;,10.2.7 内核模块module,3.module的初始化与回收,void cleanup_module(void)/模块卸载函数 unregister_chrdev(参数1,参数2);,Module

16、_init(module _init),module_exit(module _cleanup)这两个宏是在Linux内核头文件中定义的,Linux2.4中才具有。,10.3 设备驱动程序框架,include include include include include define DEMO_DEVICE_MAJOR 125define DEMO_DEVICE_NAME“demo”define DEMO_DEVICE_COMMAND1 1define DEMO_DEVICE_COMMAND2 2define DEMO_DEVICE_COMMAND3 3,1 头文件包含:编写设备驱动的时候要

17、包含内核的头文件,2 定义常量:定义模块的主设备号和模块的名称,10.3 设备驱动程序框架,module_init(demo_init);module_exit(demo_cleanup);static struct file_operation demo_device_fops=owner:THIS_MOUDLE,read:demo_read,write:demo_write,ioctl:demo_ioctl,open:demo_open,release:demo_close,;,3 函数声明;,4 文件操作结构的指针,10.3 设备驱动程序框架,static int demo_init(v

18、oid)int result;SET_MODULE_OWNER(,10.3 设备驱动程序框架,static int demo_write(struct file*flip,const char*buffer,size_t count)char dev_buf;copy_from_user(dev_buff,buffer,count);static int demo_read(struct file*flip,char*buffer,size_t count,loff_t*ppos)char dev_buf;copy_to_user(buffer,dev_buff,count);,5 各种操作,

19、10.3 设备驱动程序框架,static int demo_ioctl(struct inode*inode,struct file*file,unsigned int cmd,unsigned long arg)switch(cmd)case DEMO_DEVICE_COMMAND1:/*DEMO_DEVICE_COMMAND1处理函数*/break;case DEMO_DEVICE_COMMAND2:/*DEMO_DEVICE_COMMAND2处理函数*/break;case DEMO_DEVICE_COMMAND3:/*DEMO_DEVICE_COMMAND3处理函数*/break;re

20、turn 0;,10.3 设备驱动程序框架,static int demo_open(struct inode*inode,struct file*file)printk(KERN_CRIT“demo_device openn”);MOD_INC_USE_COUNT;return 0;static int demo_close(struct inode*inode,struct file*file)printk(KERN_CRIT“demo_device closen”);MOD_DEC_USE_COUNT;return 0;,补充:设备驱动程序开发中一些具体问题,IO PortLinux下任

21、何驱动程序都可以对任意IO进行操作,每个驱动程序都应该自己避免误用端口。有两个Kernel函数可以使用。check_region(int io_port,int off_set)request_region(int io_port,int off_set,char*devname),另:设备驱动程序开发中一些具体问题,内存操作在设备驱动中动态的开辟内存不是用malloc(),而是使用kmalloc(),回收内存使用kfree()。注意kmalloc最大只能开辟(128K16)个字节的空间。其中16字节被页描述符占用了。IO口、寄存器或者硬件设备的RAM一般占用F000000以上的地址空间,驱动

22、程序不能直接访问,要通过kernel的vremap函数获得重新映射后的地址。,另:设备驱动程序开发中一些具体问题,有些硬件需要比较大的连续内存空间做DMA传送,这块空间要一直驻留使用,但kmalloc最大只能开辟128K的内存,需要用其它方法解决。用vremap映射后的内存,不用时应用unremap释放。,另:设备驱动程序开发中一些具体问题,中断处理驱动中可以使用中断,Linux使用中断的过程如下:(1)在移植内核的时候根据硬件的情况,为每一个硬件设备分配中断号;(2)当中断产生时根据中断类型号找到中断处理子程序进行处理;(3)在驱动程序中需要将硬件的中断处理子程序注册到其中断号上。,另:设备驱动程序开发中一些具体问题,在Linux系统中,对中断的处理属于系统核心部分,设备驱动程序可以通过下面的函数来向系统申请和释放中断。int request_irq(unsigned int irq,void(*handle)(int void*,struct pt_regs*),unsigned int long flags,const char*device)int free_irq(unsigned int irq,void*dev_id);,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号