




已阅读5页,还剩37页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux字符设备驱动程序 Linux驱动程序的分类 字符设备驱动 用于驱动能够像字节流 文件 一样被访问的设备 应用程序通常可以利用open close read write等系统调用访问字符设备驱动 块设备驱动 块设备和字符设备只在系统内核内部的管理上有所区别 应用程序对于字符设备的每一个I O操作都会被内核直接传递给对应的驱动程序 而应用程序对于块设备的操作要经过虚拟文件系统 VFS 和缓冲区管理系统间接地传递给驱动程序处理 网络设备驱动 应用程序必须利用套接字 socket 接口访问网络设备 网络设备驱动程序 字符设备驱动程序基本结构 字符设备开发的基本步骤确定主设备号和次设备号实现字符驱动程序实现file operations结构体构造字符设备结构体cdev在模块加载函数中注册字符设备在模块卸载函数中注销字符设备创建设备文件节点 设备文件与设备号 为了体现 一切都是文件 的设计思想 linux将每个已安装的设备都表示为一个设备文件 设备文件通常位于 dev子目录 对于字符设备 应用程序可以利用open close read write等系统调用访问其设备文件 这些I O操作都被直接传递给该设备文件所对应的设备 每个设备文件中都存储了该设备的 主设备号 和 次设备号 一般由同一个内核模块管理的多个设备占用同一个主设备号 具体设备用次设备号标识 用mknodfilenamecmajorminor命令创建设备文件用rmfilename命令删除设备文件 注意删除设备文件并不会影响驱动模块 应用程序如何访问设备 fd1 open dev ttyS1 O RDWR 阻塞fd2 open dev ttyS1 O RDWR O NONBLOCK 非阻塞intread intfd constvoid buf size tlength intwrite intfd constvoid buf size tlength intlseek intfd offset toffset intwhence intioctl intfd intcmd void arg intclose intfd 设备号的内部表达 设备编号的内部表达dev t类型 32位 用来保存设备编号 包括主设备号 12位 和次设备号 20位 从dev t获得主设备号和次设备号 MAJOR dev t MINOR dev t 将主设备号和次设备号转换成dev t类型 MKDEV intmajor intminor 主设备号与次设备号 分配主设备号手工分配主设备号 找一个内核没有使用的主设备号来使用 includeintregister chrdev region dev tfirst unsignedintcount char name 要分配的设备编号范围的起始值 次设备号经常为0 所请求的连续设备编号的个数 和该编号范围关联的设备名称 主设备号与次设备号 动态分配主设备号 includeintalloc chrdev resion dev t dev unsignedintfirstminor unsignedintcount char name 输出的设备号 要使用的被请求的第一个次设备号 主设备号与次设备号 释放设备号 voidunregister chrdev region dev tfirst unsignedintcount 通常在模块的清除函数中调用 记录字符设备的结构体cdev 实现字符驱动程序cdev结构体 structcdev structkobjectkobj 内嵌的kobject对象 structmodule owner 所属模块 structfile operations ops 文件操作结构体 structlist headlist dev tdev 设备号 unsignedintcount cdev的kobj list count字段不用我们关系和维护 内核代劳 我们只需将其ops字段指向为我们自己的fileoperations结构 对cdev结构体的操作 操作cdev的函数 voidcdev init structcdev structfile operations structcdev cdev alloc void intcdev add structcdev dev t unsigned voidcdev del structcdev 用于初始化cdev的成员 并建立cdev和file operations之间的连接 分别向系统删除一个cdev 完成字符设备的注销 通常在模块的卸载函数中调用 分别向系统添加一个cdev 完成字符设备的注册 通常在模块加载函数中调用 函数用于动态申请一个cdev内存 file operations结构体 file operations结构体字符驱动和内核的接口 在include linux fs h定义字符驱动只要实现一个file operations结构体并注册到内核中 内核就有了操作此设备的能力 structfile operations structmodule owner loff t llseek structfile loff t int ssize t read structfile char user size t loff t ssize t write structfile constchar user size t loff t unsignedint poll structfile structpoll table struct int ioctl structinode structfile unsignedint unsignedlong int open structinode structfile int flush structfile fl owner tid int release structinode structfile file operations结构体 file operations的主要成员 structmodule owner 指向模块自身open 打开设备release 关闭设备read 从设备上读数据write 向设备上写数据ioctl I O控制函数llseek 定位读写指针mmap 映射设备空间到进程的地址空间 fileoperations的初始化 structfile operationsmy fops owner THIS MODULE llseek my llseek read my read write my write ioctl my ioctl open my open release my release file结构体 file结构代表一个打开的文件 它由内核在应用程序open时创建 并将该文件所对应的fileoperations记录在file结构中 在应用程序调用close函数 内核会释放该数据结构 structfile structfile operations f op unsignedintf flags fmode tf mode loff tf pos structdentry f dentryvoid private data file结构体 file结构体file结构 file operations结构相关的一个结构体 描述一个正在打开的设备文件 成员 loff tf pos 当前读 写位置unsignedintf flags标识文件打开时 是否可读或可写O RDONLYO NONBLOCKO SYNCstructfile operations f op文件相关的操作 指向所实现的structfile operationsvoid private data 私有数据指针 驱动程序可以将这个字段用于任何目的或者忽略这个字段 inode结构体 内核用inode结构在内部表示文件 用于存储文件访问权限 属主 组 大小 生产时间等VFS关心的信息 其字段中我们只关心i rdev 设备号 和i cdev 和该文件所对应的cdev结构 我们在创建设备文件时 内核会自动创建一个对应的inode结构体 并将其i cdev字段指向对应的字符设备结构体cdev 事先已经在内核中注册过 Inode与file的区别 file表示打开的文件描述符 多个file结构 可以指向单个inode结构 structinode dev ti rdev structcdev i cdev Inode结构体 Inode结构中的两个主要字段 dev ti rdev 对表示设备文件的inode结构 该字段包含了真正的设备编号 structcdev i cdev structcdev是表示字符设备的内核的内部结构 当inode指向一个字符设备文件时 该字段包含了指向structcdev结构的指针从一个inode中获得主设备号和次设备号 unsignedintiminor structinode inode unsignedintimajor structinode inode 字符设备驱动程序基本结构 注册设备 在模块或驱动初始化时调用Linux 2 4及之前Linux 2 6 intregister chrdev unsignedintmajor constchar name structfile operations fops 如何操作字符设备的接口 voidcdev init structcdev structfile operations intcdev add structcdev dev t unsigned 字符设备驱动程序基本结构 注销设备 在模块卸载时调用Linux 2 4及之前Linux 2 6 intunregister chrdev unsignedintmajor constchar name voidcdev del structcdev 字符设备驱动程序基本结构 设备驱动模块加载函数staticint initxxx init void cdev init 注册设备 字符设备驱动程序基本结构 设备驱动模块卸载函数 staticvoid exitxxx exit void unregister chrdev region xxx dev no 1 释放占用的设备号cdev del 注销设备 字符设备驱动程序基本结构 打开模块使用计数加1识别次设备号硬件操作 检查设备相关错误 诸如设备未就绪或类似的硬件问题 如果设备是首次打开 则对其初始化 如果有中断操作 申请中断处理程序 intopen structinode inode structfile filp 字符设备驱动程序基本结构 关闭模块使用计数减1释放由open分配的 保存在filp private data里的所有内容 硬件操作 如果申请了中断 则释放中断处理程序 在最后一次关闭操作时关闭设备 intrelease structinode inode structfile filp 字符设备驱动程序基本结构 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 指向用户空间的缓冲区 这个缓冲区或者保存将写入的数据 或者是一个存放新读入数据的空缓冲区 用户在文件中存取操作的位置 字符设备驱动程序基本结构 用户空间和内核空间之间的数据拷贝过程 不能简单的用指针操作或者memcpy来进行数据拷贝用户空间的数据是可以被换出的 会产生一个页面失效异常 用户空间的地址无法在内核空间中使用 用户空间和内核空间之间进行数据拷贝的函数 如果要复制的内存是简单类型 如char int long等 put user 和get user unsignedlongcopy from user void to constvoid user from unsignedlongcount unsignedlongcopy to user void user to constvoid from unsignedlongcount 字符设备驱动程序基本结构 读设备模板ssize txxx read structfile filp char user buf size tcount loff t f pos copy to user buf 写设备模板ssize txxx write structfile filp constchar user buf size tcount loff t f pos copy from user buf 字符设备驱动程序基本结构 ioctl函数为设备驱动程序执行 命令 提供了一个特有的入口点用来设置或者读取设备的属性信息 intioctl structinode inode structfile filp unsignedintcmd unsignedlongarg 事先定义的IO控制命令代码 arg为对应于cmd命令的参数 字符设备驱动程序基本结构 cmd参数的定义不推荐用0 x1 0 x2 0 x3之类的值Linux对ioctl 的cmd参数有特殊的定义构造命令编号的宏 IO type nr 用于构造无参数的命令编号 IOR type nr datatype 用于构造从驱动程序中读取数据的命令编号 IOW type nr datatype 用于写入数据的命令 IOWR type nr datatype 用于双向传输 type和number位字段通过参数传入 而size位字段通过对datatype参数取sizeof获得 字符设备驱动程序基本结构 Ioctl函数模板intxxx ioctl structinode inode structfile filp unsignedintcmd unsignedlongarg switch cmd caseXXX CMD1 break caseXXX CMD2 break default 不能支持的命令 return ENOTTY return0 阶段总结 阶段总结 添加驱动程序到内核 配置内核编译内核添加驱动程序到内核中 添加驱动程序到内核 配置内核配置命令包括 makeconfigmakemenuconfigmakexconfigmakegconfig可通过 上 下 左 右 键移动菜单 选择某项按 Y 取消选择按 N 如果选择某项编译为模块按 M 进入子菜单按 Enter 返回上一级菜单按 Esc 使用makeconfig makemenuconfig等命令后 会生成一个 config配置文件 是隐身文件 通过ls a才能看到 添加驱动程序到内核 编译内核可用如下命令编译内核 makeARC armCROSS COMPILE arm linux zImage源代码根目录的Makefile中将ARCH和CROSS COMPILE直接指定为arm和arm linux 如 这样就没有必要每次编译的时候都指定体系结构和交叉编译器了 只须使用下面命令就可以了 makezImage ARCH armCROSS COMPILE arm linux 添加驱动程序到内核 添加驱动程序到内核Linux2 6内核的配置系统由以下3个部分组成 Makefile 分布在Linux内核源代码中的Makefite定义Linux内核的编译规则配置文件 Kconfig 给用户提供配置选择的功能 配置工具 包括配置命令解释器 对配置脚本中使用的配置命令进行解释 配置用户界面 提供字符界面和图形界面 这些配置工具都是使用脚本语言编写的 如Tcl TK Perl等 在Linux内核中增加程序需要完成以下3项工作 将编写的源代码复制到Linux内核源代码的相应目录 在目录的Kconfig文件中增加新源代码对应项目的编译配置选项 在目录的Makefile文件中增加对新源代码的编译条目 添加驱动程序到内核 实例 在内核源代码drivers目录下为ARM体系结构新增t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 生活垃圾收集设施防雨防晒改造方案
- 光伏项目施工人员培训实施方案
- 源网荷储一体化中源荷协调互动实施方案
- 幕墙数字化深化设计实施方
- 雨水调蓄设施建设防内涝方案
- 农艺与观光协同管理方案
- 2025年幼儿保健简述题目及答案
- 护理病人考试题及答案
- 单招护理考试题库及答案
- 医学配伍题真题及答案
- 电力运行维护管理办法
- 2025年甘肃省高考政治真题卷含答案解析
- 专职安全生产管理人员综合类C证习题(含答案)
- 2025年市场监管总局机关公开遴选公务员面试模拟题及答案
- 注册安全工程师考试道路运输和其他安全安全生产实务(初级)试卷与参考答案
- 客户关系管理课件 第1章 客户关系管理概述
- 数学-湖南省长郡中学2025-2026学年高二上学期暑假作业检测(开学)试题+答案
- 构建餐饮油烟共治格局的策略及实施路径
- 前交叉韧带重建手术质量评价规范
- 《MySQL数据库教程》课件第一章数据库概述
- 铝单板幕墙专项方案
评论
0/150
提交评论