ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:19.58KB ,
资源ID:7845363      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7845363.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux设备驱动之Ioctl控制.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux设备驱动之Ioctl控制.docx

1、Linux设备驱动之Ioctl控制Linux设备驱动之Ioctl控制大部分驱动除了需要具备读写设备的能力之外,还需要具备对硬件控制的能力。一、在用户空间,使用ioctl系统调用来控制设备,原型如下:/*fd:文件描述符cmd:控制命令.:可选参数:插入*argp,具体内容依赖于cmd*/int ioctl(int fd,unsigned long cmd,.);用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。二、驱动ioctl方法:/*inode与filp两个指针对应于应用程序传递的文件描述符fd,这和传递open方法的参数

2、一样。cmd 由用户空间直接不经修改的传递给驱动程序arg 可选。*/int (*ioctl) (struct inode *inode,struct file *filp, unsigned int cmd,unsigned long arg);在驱动程序中实现的ioctl函数体内,实际上是有一个switch case结构,每一个case对应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事情,因为设备都是特定的。关键在于怎么样组织命令码,因为在ioctl中命令码是唯一联系用户程序命令和驱动程序支持的途径。在Linux核心中是这样定义一个命令码的:_| 设备类型 |

3、序列号 | 方向 | 数据尺寸 |-|-|-|- | 8 bit | 8 bit |2 bit |814 bit|-|-|-|- |这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数据传送方向和数据传输尺寸。1、定义命令:内核提供了一些宏来帮助定义命令:/nr为序号,datatype为数据类型,如int_IO(type, nr ) /没有参数的命令_IOR(type, nr, datatype) /从驱动

4、中读数据_IOW(type, nr, datatype) /写数据到驱动_IOWR(type,nr, datatype) /双向传送定义命令例子:#define MEM_IOC_MAGIC m /定义类型#define MEM_IOCSET _IOW(MEM_IOC_MAGIC,0,int)#define MEM_IOCGQSET _IOR(MEM_IOC_MAGIC, 1, int)2、实现命令:定义好了命令,下一步就是要实现ioctl函数了,ioctl的实现包括三个技术环节:1)返回值;ioctl函数的实现是根据命令执行的一个switch语句,但是,当命令不能匹配任何一个设备所支持的命令时

5、,通常返回-EINVAL(非法参数);2)参数使用;用户使用int ioctl(int fd,unsinged long cmd,.)时,.就是要传递的参数;再通过int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)中的arg传递;如果arg是一个整数,可以直接使用;如果是指针,我们必须确保这个用户地址是有效的,因此,使用之前需要进行正确检查。内部有检查的,不需要检测的: copy_from_user copy_to_user get_user put_user需要检测

6、的: _get_user _put_user检测函数access_ok():/*type :是VERIFY_READ 或者VERIFY_WRITE用来表明是读用户内存还是写用户内存;addr:是要操作的用户内存地址;size:是操作的长度。如果ioctl需要从用户空间读一个整数,那么size参数就等于sizeof(int);返回值:Access_ok返回一个布尔值:1,是成功(存取没问题);0,是失败,ioctl返回-EFAULT;*/static inline int access_ok(int type, const void *addr, unsigned long size)3)命令操

7、作;switch(cmd) case: . .三、ioctl实例分析:(1)memdev.h:#ifndef _MEMDEV_H_#define _MEMDEV_H_#include #ifndef MEMDEV_MAJOR#define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/#endif#ifndef MEMDEV_NR_DEVS#define MEMDEV_NR_DEVS 2 /*设备数*/#endif#ifndef MEMDEV_SIZE#define MEMDEV_SIZE 4096#endif/*mem设备描述结构体*/struct mem_dev char *

8、data; unsigned long size; ;/* 定义幻数 */#define MEMDEV_IOC_MAGIC k/* 定义命令 */#define MEMDEV_IOCPRINT _IO(MEMDEV_IOC_MAGIC, 1)#define MEMDEV_IOCGETDATA _IOR(MEMDEV_IOC_MAGIC, 2, int)#define MEMDEV_IOCSETDATA _IOW(MEMDEV_IOC_MAGIC, 3, int)#define MEMDEV_IOC_MAXNR 3#endif /* _MEMDEV_H_ */(2)memdev.c:(驱动程序)

9、#include #include #include #include #include #include #include #include #include #include #include #include memdev.hstatic int mem_major = MEMDEV_MAJOR;module_param(mem_major, int, S_IRUGO);struct mem_dev *mem_devp; /*设备结构体指针*/struct cdev cdev; /*文件打开函数*/int mem_open(struct inode *inode, struct file

10、 *filp) struct mem_dev *dev; /*获取次设备号*/ int num = MINOR(inode-i_rdev); if (num = MEMDEV_NR_DEVS) return -ENODEV; dev = &mem_devpnum; /*将设备描述结构指针赋值给文件私有数据指针*/ filp-private_data = dev; return 0; /*文件释放函数*/int mem_release(struct inode *inode, struct file *filp) return 0;/*IO操作*/int memdev_ioctl(struct

11、inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) int err = 0; int ret = 0; int ioarg = 0; /* 检测命令的有效性 */ if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC) return -EINVAL; if (_IOC_NR(cmd) MEMDEV_IOC_MAXNR) return -EINVAL; /* 根据命令类型,检测参数空间是否可以访问 */ if (_IOC_DIR(cmd) & _IOC_READ) err = !acc

12、ess_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd); if (err) return -EFAULT; /* 根据命令,执行相应的操作 */ switch(cmd) /* 打印当前设备信息 */ case MEMDEV_IOCPRINT: printk(nn); break; /* 获取参数 */ case MEMDEV_IOCGETDATA: ioarg =

13、 1101; ret = _put_user(ioarg, (int *)arg); break; /* 设置参数 */ case MEMDEV_IOCSETDATA: ret = _get_user(ioarg, (int *)arg); printk(nn,ioarg); break; default: return -EINVAL; return ret;/*文件操作结构体*/static const struct file_operations mem_fops = .owner = THIS_MODULE, .open = mem_open, .release = mem_relea

14、se, .ioctl = memdev_ioctl,;/*设备驱动模块加载函数*/static int memdev_init(void) int result; int i; dev_t devno = MKDEV(mem_major, 0); /* 静态申请设备号*/ if (mem_major) result = register_chrdev_region(devno, 2, memdev); else /* 动态分配设备号 */ result = alloc_chrdev_region(&devno, 0, 2, memdev); mem_major = MAJOR(devno);

15、if (result 0) return result; /*初始化cdev结构*/ cdev_init(&cdev, &mem_fops); cdev.owner = THIS_MODULE; cdev.ops = &mem_fops; /* 注册字符设备 */ cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS); /* 为设备描述结构分配内存*/ mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL); if (!mem_devp) /*申请失败*/

16、 result = - ENOMEM; goto fail_malloc; memset(mem_devp, 0, sizeof(struct mem_dev); /*为设备分配内存*/ for (i=0; i MEMDEV_NR_DEVS; i+) mem_devpi.size = MEMDEV_SIZE; mem_devpi.data = kmalloc(MEMDEV_SIZE, GFP_KERNEL); memset(mem_devpi.data, 0, MEMDEV_SIZE); return 0; fail_malloc: unregister_chrdev_region(devno

17、, 1); return result;/*模块卸载函数*/static void memdev_exit(void) cdev_del(&cdev); /*注销设备*/ kfree(mem_devp); /*释放设备结构体内存*/ unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/MODULE_AUTHOR(David Xie);MODULE_LICENSE(GPL);module_init(memdev_init);module_exit(memdev_exit);(3)app-ioctl.c(应用程序)#include

18、#include#include#include#include memdev.h /* 包含命令定义 */int main() int fd = 0; int cmd; int arg = 0; char Buf4096; /*打开设备文件*/ fd = open(/dev/memdev0,O_RDWR); if (fd 0) printf(Open Dev Mem0 Error!n); return -1; /* 调用命令MEMDEV_IOCPRINT */ printf(n); cmd = MEMDEV_IOCPRINT; if (ioctl(fd, cmd, &arg) 0) prin

19、tf(Call cmd MEMDEV_IOCPRINT failn); return -1; /* 调用命令MEMDEV_IOCSETDATA */ printf(n); cmd = MEMDEV_IOCSETDATA; arg = 2007; if (ioctl(fd, cmd, &arg) 0) printf(Call cmd MEMDEV_IOCSETDATA failn); return -1; /* 调用命令MEMDEV_IOCGETDATA */ printf(n); cmd = MEMDEV_IOCGETDATA; if (ioctl(fd, cmd, &arg) 0) prin

20、tf(Call cmd MEMDEV_IOCGETDATA failn); return -1; printf(nn,arg); close(fd); return 0; /*/很棒!谢谢楼主!下面这些自动化脚本,锦上添花 :)#!/bin/sh# install_mod.shmodule=memdevdevice=memdevmode=664 # Group: since distributions do it differently, look for wheel or use staffif grep staff: /etc/group /dev/null; then group=sta

21、ffelse group=wheelfi # remove stale nodesrm -f /dev/$device? # invoke insmod with all arguments we got# and use a pathname, as newer modutils dont look in . by default/sbin/insmod -f ./$module.ko $* | exit 1major=cat /proc/devices | awk $2=$module print $1mknod /dev/$device0 c $major 0mknod /dev/$de

22、vice1 c $major 1ln -sf $device0 /dev/$device# give appropriate group/permissionschgrp $group /dev/$device0-1chmod $mode /dev/$device0-1#!/bin/sh#unstall_mod.shmodule=memdevdevice=memdev # invoke rmmod with all arguments we got/sbin/rmmod $module $* | exit 1 # remove nodesrm -f /dev/$device0-1 /dev/$device exit 0

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1