1 / 41

Linux 设备驱动概述

Linux 设备驱动概述. 成研所操作系统团队. Linux 设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术. 目录. 设备驱动的作用. 系统与硬件 的接口 部分 应用与硬件 的接口 让硬件为用户可用,一般驱动本身不给用户 定制策略 许多驱动程序是同用户程序一起发行的,这样对于硬件使用 策略 提供给了用户态的 应用层. 设备分类. 字符型设备 仅仅是 数据通道 ,其读写实质是数据的输入和输出 存取时 没有缓存 块设备 文件系统 的宿主 块设备的读写,内核都有缓存来支持,块设备必须能够 随机存取 网络设备

holly
Download Presentation

Linux 设备驱动概述

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Linux设备驱动概述 成研所操作系统团队

  2. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  3. 设备驱动的作用 • 系统与硬件的接口 • 部分应用与硬件的接口 • 让硬件为用户可用,一般驱动本身不给用户定制策略 • 许多驱动程序是同用户程序一起发行的,这样对于硬件使用策略提供给了用户态的应用层

  4. 设备分类 • 字符型设备 • 仅仅是数据通道,其读写实质是数据的输入和输出 • 存取时没有缓存 • 块设备 • 文件系统的宿主 • 块设备的读写,内核都有缓存来支持,块设备必须能够随机存取 • 网络设备 • 不再调用read/write,而是调用数据包协议 • 上层协议自动调用发送程序 • 硬件中断通知接收

  5. 设备文件 • 设备文件 • Linux认为“一切皆文件”,设备驱动也可以像文件一样读、写、开、关。 • 驱动设备文件都在/dev下,如/dev/hda1 • Block型设备文件类型为b,Character型设备为c,Socket设备为s • 查看设备文件 • file 设备名 • ls -l 设备名

  6. 设备文件 • 主设备号和从设备号 • 针对字符型和块设备文件,使用主、从设备号来描述设备 • 主设备编号表示某种驱动程序 • 辅设备区分不同设备 例如/dev/hda1、2、3(block 3/1) • 同一块硬盘的3块分区 • 3/1的3为主设备号,1为从设备号 • 创建设备文件 • mknod harddisk b 3 0

  7. 设备文件 • /proc目录 • 设备文件与驱动的桥梁 • 访问设备文件时,查找/proc目录下的值,确定驱动模块 • /proc目录下的文件为虚拟文件,实际是内核在内存中的参数。 • 每次启动系统,自动将/etc/fstab中的设置信息作为proc文件加载到/proc目录下。

  8. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  9. 内核态与用户态 • 内核态 • 内核态程序是运行在特权模式下,可以运行特权指令,可以访问特殊地址空间。 • 运行于内核态的进程拥有独立的地址空间,各进程互不影响,因此相对于用户态的程序安全而可靠,独立而封闭。 • 设备驱动通常运行于内核态 • 用户态 • 一般为应用程序 • 用户态进程优先级低于内核态进程 • 独立性、安全性不如内核态

  10. 设备驱动加载方式 • 内核 • 包含最基本的驱动 • CPU • PCI总线 • TCP/IP协议 • APM(高级电源管理) • VFS • 内核模块 • 一般的外设驱动 • 不一定是硬件的驱动,如ext3文件系统驱动 • 动态加载进内核后,成为内核一部分

  11. 模块命令 • lsmod • 列出已加载的模块 • modprobe • 智能插入模块。根据模块间依存关系,以及/etc/modules.conf文件中的内容插入。 • insmod • 插入模块,但不会解决依赖关系。 • rmmod • 删除模块 • modinfo • 查看模块信息

  12. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  13. 字符型设备注册 • register_chrdev注册函数 int register_chrdev (unsigned int major, constchar * name, struct file_operations *fops); major:被请求的主设备号 name:设备名称 fops:一个指向一组操作(open,read等等)表的指 针。这个表的每一个项都指向由驱动程序定义的 处理相应请求的函数。

  14. 文件操作数据结构 • file_operations结构:由内核调用来访问驱动程序的函数 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 *); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *) }

  15. 主要操作 • open • 递增使用计数 • 检查设备特定的错误(如未就绪或类似硬件问题) • 如果设备是首次打开,则对其初始化 • 识别次设备号,并且如果有必要,更新f_op指针 • 分配并填写被置于filp->private_data(驱动程序自定义的数据区)里的数据结构

  16. 主要操作 • release (与open相反) • 释放由open分配的、保存在filp->private_data中的所有内容 • 在最后一次关闭操作时关闭设备 • 使用计数减1 • read/write • 从设备拷贝数据给应用程序(或相反) • 使用copy_to_user和copy_from_user实现内核空间与用户空间的虚拟内存拷贝。

  17. 竞态与解决方案 • 为何出现竞态 • 当多个线程同时访问相同的资源 • 信号量 • 引起调用者睡眠,它把进程从运行队列上拖出去,除非获得锁 • 耗资源大,适合单处理器,保持时间长的情况 • 只能在进程上下文中访问 • 自旋锁 • 如果自旋锁已经被别的执行单元保持,调用者就一直循环查看是否该自旋锁的保持者已经释放了锁 ,即原地打转 • 适合多处理器、SMP环境 • 可在任何上下文使用

  18. 设备操作通信机制 • 为何需要同步机制 • 要读取或写入的数据需要同其他硬件交换而得到 • 阻塞与非阻塞 • 阻塞:在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作 • 非阻塞:进程在不能进行设备操作时,不进行挂起,直接返回 • 异步触发 • 一旦设备就绪,向所有注册异步触发的进程发送SIGIO信号,这样应用程序根本就不需要查询设备状态 ,效率很高。

  19. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  20. 块设备驱动注册 • int register_blkdev (unsigned int major, const char *name, struct block_device_operations *bdops); major:主设备号 *name:设备名 *bdops:指向块设备数据结构block_device_operations的指针

  21. bdops数据结构 • block_device_operations { int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); int (*check_media_change) (kdev_t); int (*revalidate) (kdev_t); struct module *owner; };

  22. 主要操作 • open和release • 同字符型设备类似 • check_media_change • 用于支持可移动设备,不支持的设置成NULL • 检查自从上次访问以来设备是否发生过变化 • kdev_t参数为1表示发生变化 • revalidate • 主要用于支持可移动设备 • 磁盘发生变化之后重新初始化驱动程序的状态 • 通常用来更新内部的状态信息以便反映出新的设备

  23. 读、写的request机制 • 对块设备的读写通过一种叫request的机制间接实现: blk_init_queue (request_queue_t *queue, request_fn_proc *request) • 在块设备的注册过程中,需要初始化request队列,这一动作通过blk_init_queue来完成。blk_init_queue函数建立队列,并将该驱动程序的 request函数关联到队列

  24. 读、写的request机制 • request_fn_proc是一个函数指针类型,定义为: typedef void (request_fn_proc) (request_queue_t *q); struct request { struct list_head queue; int elevator_sequence; kdev_t rq_dev; int cmd; /* READ or WRITE */ } • rfn函数根据输入的request->cmd来决定读操作和写操作。 • 系统内核决定何时调用rfn函数进行实际的物理读写操作;

  25. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  26. 主要设计内容 体系结构

  27. 网络接口设备 • Linux中,把所有网络设备都抽象为一个接口,这个接口提供对所有网络设备的操作集合 • 一个网络接口必须在device数据结构中注册自己,从而在与外部世界交换包时可以被调用 • 网口设备既包括纯软件网络设备接口,如环路(Loopback),也可以包括硬件网络设备接口,如以太网卡

  28. 核心数据结构 • 网络驱动程序的核心数据结构net_device • 该数据结构定义了所有网络设备驱动的属性和方法,包括init函数、open和stop函数、包发送函数hard_ start_xmit,以及中断处理函数等 • 位置: </include/linux/netdevice.h> • 注册函数register_netdevice register_netdev (struct net_device *dev);

  29. 数据包操作 • 数据包数据结构sk_buff • 内核处理后的每一个数据包位于一个socket缓冲区结构sk_buff中 • 该结构定义了数据长度,数据缓冲的指针。以及各种协议头的定义 • 位置:</Include/Linux/skbuff.h>

  30. register_netdevice init open hard_header hard_start_xmit 数据包操作 • 数据包发送

  31. 数据到达 产生中断信号 数据包接收程序 netif_rx 数据包操作 • 数据包接收 见 /linux/net/core/dev.c

  32. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  33. 安装中断处理程序 • 申请中断 int request_irq (unsigned int irq, void (*handler) (int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id) irq:要申请的硬件中断号 handler:中断发生时,系统调用它传递dev_id参数 irqflags:中断处理属性 dev_id:中断共享时使用

  34. 安装中断处理程序 • 释放中断free_irq void free_irq (unsigned int irq,void *dev_id) • 调用时机 • request_irq: 设备第一次打开、硬件被告知产生中 断之前 • free_irq:最后一次关闭设备、硬件被告知不要再 中断处理器之后

  35. 快中断与慢中断 • 2者区别 • 快中断:保证中断的原子处理, “开启中断”处理器标志位(IF)是关闭的,因此在服务该中断时不允许被中断。 • 慢中断:不保证。调用慢速中断处理时,内核启动微处理器的中断报告,因此在运行慢速中断处理程序时其它中断仍可以得到服务

  36. 中断的底半部处理机制 • 使用底半部机制的缘由 • 系统响应一次设备中断需要完成一定数量的工作,但是中断处理程序需要尽快结束而不是中断阻塞的时候过长,这两个需求彼此冲突。 • 两半部的功能 • 上半部:在屏蔽中断的上下文中运行,用于完成关键性的处理动作。 • 底半部:完成中断事件的大多数使命,可被新的中断打断。

  37. 中断的底半部处理机制 • 底半部的实现方式 • mark_bh方法(2.4以前) • task_let方法 (2.4引入) • struct tasklet_struct{struct tasklet_struct *next; /* 队列指针 */unsigned long state; /* tasklet的状态*/atomic_t count; /* 引用计数,1表示disabled */void (*func)(unsigned long); /* 函数指针 */unsigned long data; /* func(data) */};

  38. Linux设备驱动简介 内核和驱动模块 字符型设备 块设备 网络接口设备 中断处理 常用调试技术 目录

  39. 调试方法 • 打印调试 • 内核命令printk实现与print类似功能。 • 8种日志级别,根据严重程度对消息进行分类。 • Linux处理消息可以在任何地方调用printk • 查询调试 • 为避免大量输出信息,设置几个ioctl命令 • ioctl命令从驱动程序空间复制相关数据到进程空间,在进程空间里检查这些数据。 • 获取2进制信息,速度较快 • 使用观察点调试 • strace工具

  40. 调试器和工具 • 最好的工具是自己的大脑 • gdb • 支持用户应用的基本调试功能 • 支持内核运行查看 • kgdb • 支持x86 CPU • 主机-目标机调试模式 • 在内核上进行gdb调试功能

  41. 谢 谢

More Related