




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
作者sola设备驱动程序的设计主要需要2步来完成1. 分配主设备号动态分配(重点)或者静态分配2. 创建设备文件手动创建和 自动创建3. 设备注册 添加及注销i. 分配cdevii. 初始化cdeviii. 添加cdeviv. 设备注销4. 设备操作的实现(即相关方法的实现)预备知识:首先着重介绍3个非常重要的结构体Struct File结构体代表一个打开的设备文件,系统中每个打开的文件在内核中都有一个与之关联的struct file,例如当我调用linux库函数ssize_t read(int fd,void * buf ,size_t count);时它实际上是调用了内核中的ssize_t vfs_read(struct file *file, char _user *buf, size_t count, loff_t *pos)函数,内核会传给他一个参数即Struct file*file,然后通过此结构的f_op成员调用相关的函数,也就是说我们执行read函数实际上是调用了f_op中指定的函数,见下图,这是内核中的一段代码:你一定会疑问f_op是什么,这个f_op类型就是我一会将说到的第二个结构体Struct file_operation当然struct file结构体的成员相当多,但是其中有4个是常用的,第一个刚才已经提到了const struct file_operations *f_op; /一会将讲到,这里你只需知道这个成员中装有多种函数指针unsigned int f_flags;/该成员是文件标志。void *private_data;/该成员是系统调用时保存状态信息非常有用的资源。你可以暂时将其当做一块可用存放数据的指针loff_t f_pos;/这个是文件的读写位置,我们用的lseek函数其实就是影响到内核中的它来改变文件中的位置struct file_operations结构这个结构师一个函数指针的集合,定义了能在设备上进行的操作,到这里你应该明白我们系统调用的函数实质上就是间接调用这个结构中指定的函数主要成员有这些Struct file_operations mem_fops=.owner = THIS_MODULE,.llseek = mem_seek;.read = mem_read,.write = mem_write,.ioctl = mem_ioctl,.open = mem_open,.release = mem_release,;各个成员由名字就可看出他应该对用的函数了Struct inode结构体它记录了文件的物理信息,简单的说,每个存储设备或存储设备的分区被格式化成文件系统后都会对应两部分,一部分为inode,另一部分为Block,block用来存储数据,而inode则记录了这些被存储的数据的属性(包括文件大小,归属的用户组,读写权限,设备号。)这里我们注重关心的成员就是 dev_t i_rdev 设备号(马上就讲到设备号)然后我们讲一下和为设备号我们都知道在linux下每一个设备都对应一个文件,对文件的操作就可以控制设备,那么设备文件是如何与字符设备建立联系的那,答案就是通过设备号设备号是一个32位的长整型,高12位对应主设备号,低20位对用次设备号也就是说在linux下你可以安装2的12次方个不同的设备和2的20次方个同类型的设备分类:主设备号:用来反映设备类型从设备号:用来区分在同一主设备号下的不同文件设备号相关操作:如何创建设备号?答:通过MKDEV(主设备号,次设备号)内核如何描述设备号?答:通过dev_t 刚才我们在struct inode中已经见过如何从dev_t中分解出主设备号?答:通过宏MAJOR(dev_t dev)如何从dev_t中分解出次设备号MINOR(dev_t dev)好了,预备知识碎片已经凑齐,让我来学习一下驱动程序的设计的简单方法第一步 分配主设备号有两种分配方法:方法一.静态分配首先静态分配的实质就是自己找一个没有被系统使用的设备号来注册系统的设备号都存放在内核目录下的Documention/devices.txt文件中,你需要从中找一个没有被使用的设备号其次使用register_chrdec_region函数来注册这个设备号Int register_chrdev_region(dev_t from,unsignedCount,const char*name)Form为你希望申请的设备号,也就是你找的没有被使用的设备号Count 在这个设备号下你希望使用多少个设备Name:设备名(它将被体现在/proc/devices中)静态分配的缺点:因为你的主设备号时随机选定的,一旦驱动被广泛使用,可能会导致设备号冲突,而使驱动程序无法注册方法二.动态分配由系统为你分配主设备号首先调用函数Int alloc_chrdev_region(dev_t*dev,unsignedBaseminor,unsigned count,const char*name)参数即功能:请求内核分配count个设备号,而且次设备号从baseminor开始,分配到的设备号通过dev返回,name表示设备名,体现在/proc/devices中最后.对于静态分配和动态分配当不需要使用设备时将设备号注销,因为设备号是比较宝贵的东西Void unsigister_chrdev_region(dev_t from,unsigned count)释放从主设备号form开始的count个设备号第二部创建设备文件两种方法:方法一.手动创建(少用)使用mknod命令方法二. 自动创建在(2.4内核中)只需要调用这一个函数Devfs_register(devfs_handle_t dir,const char *name,sunsigned int flags,unsigned int major,Unsigned int minor,umode_t mode,void*ops,void *info)参数介绍:Dir:目录名,为NULL表示为/dev下创建设备文件Name:文件名Flags:创建标识Major:主设备号Minor:次设备号Mode:创建模式Ops:操作函数集Info:通常为空在2.6内核中devfs不存在改用udev改用udev创建设备文件需要调用两个函数: 首先在驱动程序初始化代码中调用class_create为该设备创建一个class 然后再为每个设备调用device_create创建对应的设备文件Struct class *myclass = class_create(THIS_MODULE,“my_device_driver”);/表示创建一类设备文件这类设备文件名为”my_device_driver”Device_create(myclass,NULL,MKDEV(major_num,0),NULL,”my_device”);/当驱动被加载时udev(mdev)就会自动在/dev下创建my_device设备文件注意:在busybox中默认是不支持mdev的所以要配置busybox让它支持medv设备的注册添加及注销(注意这些设备操作不仅使用于字符设备驱动程序):字符设备使用struct cdev来描述这里就要用到我们上面将的3个结构了struct file struct inode struct file_operation 主要分为4个步骤1. 分配cdev动态分配使用函数struct cdev*cdev_alloc(void),如果为静态分配就不需要调用了2. 初始化cdevVoid cdev_init(struct cdev*cdev,const struct file_operations *fops)Cdev为需要被初始化的字符设备结构,fops中是需要加入到设备中的各种函数操作3. 添加cdev即设备注册,使用函数int cdev_add(struct cdev*p,dev_t dev,unsigned count)参数p:需要被加入到内核的字符设备结构,也就是刚被初始化的那个Dev设备号 count添加的设备个数个人认为,是将设备操作和设备号相关联4. 设备注销使用cdev_del(struct cdev*p)P是要注销的字符设备结构各类设备操作的实现:上面我们在初始化cdev时用到了struct_operation结构 我说过这个结构中封装了各种设备操作函数指针,下面就来看一下这些函数打开操作Int (*open)(struct inode*,struct file*)这是设备文件上的第一个方法,并不要求驱动程序一定要实现它,如果该选项为NULL,设备的打开操作永远成功Inode对应类文件属性,到你调用系统函数open()指定的文件属性就会通过该参数传入释放操作Void (*release)(struct inode*,struct file*)当设备文件被关闭时,调用此函数,与open类似读操作Ssize_t (*read)(struct file*,char _user*,size_t,loff_t*)写操作Ssize_t (*write)(struct file*,const char _user*,size_t,loff_t*)控制Int (*ioctl) (struct inode*,struct file*,unsigned int,unsigned long)对应于用户空间的函数:Int ioctl(int fd,unsigned long cmd,)点表示一个可选参数,存在与否取决于第二个参数Loctl驱动方法的设计Cmd参数是从用户空间传下来的,可选参数arg以一个unsigned long形式传递下来如果cmd不涉及数据的传输,则第三个参数的值无意义实现方法:1. 定义命令(参数cmd的处理)Loctl命令(cmd)被划分为几个字段如下: Type 幻数(类型):表明这是哪个设备的命令 Number 序号,表明设备命令中的第几个 (8位宽) Direction 数据的传递方向: _IOC_NONE(没有数据传输) _IOC_READ读取数据 _IOC_WRITE 写入数据 Size 用户数据的大小(13/14位宽) 我们可以使用一下几个宏来定义loctl的命令参数(type指的幻数,nr指的是序号)_IO(TYPE,nr);/定义没有参数的命令_IOR(type,nr,datatype);/从驱动中读取数据_IOW(type,nr,datatype);/写入数据到驱动_IOWR(type,nr,datatype);/双向传送的命令定义范例:#define MEM_ICO_MAGIC m定义幻数#define MEM_IOCSET_IOW(MEM_IOC_MAGIC,0,int)/表示写入设备驱动程序的命令#define MEM_IOCGQSET_IOR(MEM_IOCMAGIC,1,int)/表示读取设备驱动程序的命令2. 返回值Loctl通常是根据命令执行的一个switch语句当命令不匹配时返回-EINVAL3. 参数arg的处理对于参数arg,如果从用户空间传下去得就是一个整形那么可以直接使用,如果传下去得是一个指针,那么用的时候需要进行检测以保证指针有效对于指针的检测有两种情况:A. 不需要检测这些内核函数本身就带有检测,使用这些函数就不需要检测Copy_from_userCopy_to_userGet_userPut_userB. 需要检测使用这两个内很函数之前需要先检测_get_user_put_user检测的实现Int access_ok(int type,const,void*addr,unsigned long size)参数介绍:Type:检测类型VERIFY_READ VERIFY_WRITE用来表明是读用户内存还是写用户内存Addr:是要操作的用户内存地址Size:使用的长度返回:1成功 0失败示例注意:_IOC_DIR(cmd)&_IOC_READ表示将cmd命令中的方向字段与_IOC_READ相与来判断该命令的方向是否为读取为什么 _IOC_READ对应于VERIFY_WRITE?因为_IOC_READ表示的是从内核空间读取数据到用户空间,对于内核空间来说就相当于向用户空间写入数据Poll操作,对用与select系统调用Int select(int maxfd,fd_set*readfds,fd_set*writefds,Fe_set*exceptfds,const struct timval*timeout)作用:select系统调用用于多路监控,当没有一个文件满足要求时将阻塞进程调用参数介绍:maxfd文件描述符的范围Readfds被监控的文件描述符集Writefds 被写监控的文件描述符集Exceptfds 被异常监控的文件描述符集Timeout定时器当timeout值为0时,表示不管是否文件满足要求都立即返回为NULL(空指针是),select将阻塞进程,直到某个文件满足要求为整数时,就是等待最长时间返回值:1. 正常情况下返回满足要求的文件描述符的个数2. 经过timeout等待后仍无文件满足要求返回值为03. 如果select被某
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五年户外广告设施保洁劳务分包合同书范本
- 二零二五年户外广告牌立体造型设计与施工合同
- 2025版监管金融监管总局三连发金融业务合规审查合同
- 二零二五年婚礼纪婚车租赁与婚庆策划专属合同
- 二零二五年养老产业担保合同范本解析
- 2025版新能源项目采购合同范本
- 2025版建筑行业借款合同范本
- 2025版餐饮业冷链物流运输合作协议书
- 二零二五年度城市核心区精装公寓租赁合同模板
- 2025版建筑劳务分包合同标准文本
- 登革热诊疗方案(2024年版)
- 房地产经济学(第三版)课件全套 谢经荣 第1-10章 绪论-房地产市场调控政策
- 2024版标本采集课件
- 专题09 Module 5语法Grammar 特殊疑问句的用法-2021-2022学年七年级下册单元重难点易错题精练(外研版)
- 医院建设动火作业应急预案
- 《工艺管理与改善》课件
- 《交通事故车辆及财物损失价格鉴证评估技术规范》
- 品管圈PDCA改善案例-降低住院患者跌倒发生率
- 烂尾楼续建报告范文
- 心理危机干预的伦理问题探讨-洞察分析
- 智慧校园医疗系列
评论
0/150
提交评论