字符设备之ioctl
来源:互联网 发布:社会支持网络理论案例 编辑:程序博客网 时间:2024/06/11 22:05
1.ioctl()函数的存在意义:
除了简单的数据传输之外,大部分设备还可以执行一些其他的动作,比如用户空间请求设备锁门、弹出介质、改变波特率等.这些动作可以通过ioctl来实现.
2.ioctl()函数的参数说明:
ioctl()函数原型如下:
int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);各参数的意义说明如下:
inode:对应于应用程序传递的设备文件节点,和open相同;filp:对就于应用程序传递的设备文件描述符,和open相同;第三个参数比较特别,它虽然是一个无符号整形,在标准的做法里面,它是一个"位数据".每个位都是有规定的意义的.如下:
bit[31]~bit[24]:一共8位.所谓的"幻数",表征此ioctl命令的隶属设备,一般是某个字符.后续所有的ioctl命令对应的都有这个公共部分.如:
#define SCULL_IOC_MAGIC 'k'SCULL_IOC_MAGIC将作为公共部分来参与到后续的ioctl命令中.因为它是表征后续的ioctl命令隶属于哪个驱动而不是具体的某个命令.内核将此位段标识为"type".
bit[23]~bit[17]:一共8位,表示ioctl的序号.比如一个驱动里面支持16个ioctl命令,则可以排序为1~16.如:
#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1, int)#define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC, 2, int)#define SCULL_IOCTQUANTUM _IO(SCULL_IOC_MAGIC, 3)#define SCULL_IOCTQSET _IO(SCULL_IOC_MAGIC, 4)#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5, int)#define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC, 6, int)#define SCULL_IOCQQUANTUM _IO(SCULL_IOC_MAGIC, 7)#define SCULL_IOCQQSET _IO(SCULL_IOC_MAGIC, 8)#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9, int)#define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10, int)#define SCULL_IOCHQUANTUM _IO(SCULL_IOC_MAGIC, 11)#define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC, 12)上述的1~12便是对应bit[23]~bit[17]的设置.内核将此位段标识为"number".
bit[16]~bit[15]:一共两位,标识数据的传输方向.此时的方向是在用户空间的角度看的.比如标识此命令是用户读还是写还是可读可写.这两个bit的设备可以通过内核提供的宏_IOW、_IOR和_IOWR来设置.如下:
#define SCULL_IOCSQUANTUM _IOW(SCULL_IOC_MAGIC, 1, int)#define SCULL_IOCSQSET _IOW(SCULL_IOC_MAGIC, 2, int)#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5, int)#define SCULL_IOCGQSET _IOR(SCULL_IOC_MAGIC, 6, int)#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9, int)#define SCULL_IOCXQSET _IOWR(SCULL_IOC_MAGIC,10, int)其中"W"表征"写","R"表征"读".内核将此位段标识为"direction".
bit[13]~bit[0]:所涉及的用户数据的大小,以字节为单位,是对宏_IOWR、_IOW、_IOR的第三个参数用sizeof取得.比如下面命令:
#define SCULL_IOCXQUANTUM _IOWR(SCULL_IOC_MAGIC, 9, int)则此位段值为sizeof(int) = 4.内核将此位段标识为size.
第四个参数也是比较特别,特别在两点:
1).它的存在与否与第二个参数息息相关,如果参数cmd涉及到参数的传递,则需要它来承载参数的传递桥梁,否则其存在与否就一点意义都没有了;2).它恒为unsigned long类型,无论用户空间在arg上传递的是一个整形数据还是指针,它都以unsigned long的形式传递给内核.因此,当用户空间传递的是一个指针的时候,必须对其进行检查.如果传递过来是一个常规数据,直接使用即可.
针对第2)点,我们需要对用户传递过来的参数指针的合法性进行检查,以确保其对内核空间是有效的.如果用copy_to_user()和copy_from_user()两个函数来保证指针的有效性,未免有点"牛刀杀鸡"的嫌疑.这里推荐使用access_ok()函数.原型如下:
int access_ok(int type,const void *addr,unsigned long size);各参数意义如下:
type:应该为VERIFY_READ或VERIFY_WRITE,标识读或写入用户空间,其中VERIFY_WRITE是VERIFY_READ的超集,当读写动作都需要时,则需要用VERIFY_WRITE标识;addr:用户空间的指针;size:字节数,如果ioctl从用户空间读取一个整数,size就是sizeof(int).access_ok()函数的返回值:1表示成功;0表示失败.
针对传递过来的参数是指针,可以通过下面的形式来引用其指向内容:
retval = __get_user(scull_quantum,(int __user *)arg);这里需要注意的是把unsigned long arg强制类型转化为(int __user *)指针.
3.ioctl()的返回值:
当出错时,驱动中一般返回-ENVAL或-ENOTTY.
4.ioctl()所涉及到的数据交互:
ioctl()涉及到的数据量交互都比较小,如果用copy_to_user()和copy_from_user()显得"牛刀杀鸡"而且浪费一定的系统资源.如果只涉及到一个简单的变量传递,可以调用下面两个函数:
get_user(x,ptr):
get_userNameget_user -- Get a simple variable from user space.Synopsisget_user ( x, ptr);ArgumentsxVariable to store result.ptrSource address, in user space.ContextUser context only. This function may sleep.DescriptionThis macro copies a single simple variable from user space to kernel space. It supports simple types like char and int, but not larger data types like structures or arrays.ptr must have pointer-to-simple-variable type, and the result of dereferencing ptr must be assignable to x without a cast.Returns zero on success, or -EFAULT on error. On error, the variable x is set to zero.
put_user(x,ptr):
put_userNameput_user -- Write a simple value into user space.Synopsisput_user ( x, ptr);ArgumentsxValue to copy to user space.ptrDestination address, in user space.ContextUser context only. This function may sleep.DescriptionThis macro copies a single simple value from kernel space to user space. It supports simple types like char and int, but not larger data types like structures or arrays.ptr must have pointer-to-simple-variable type, and x must be assignable to the result of dereferencing ptr.Returns zero on success, or -EFAULT on error.
- 字符设备之ioctl
- 添加字符设备ioctl
- linux驱动:[3]高级字符设备驱动之ioctl
- 字符设备(4)ioctl
- 设备驱动之---ioctl()
- 带Ioctl命令的字符设备驱动程序
- linux字符设备驱动的 ioctl 幻数
- linux内核ioctl(字符设备驱动)
- linux字符设备驱动的 ioctl 幻数
- linux字符设备驱动的 ioctl 幻数
- 使用ioctl方法创建字符设备驱动
- ioctl---字符设备的控制技术
- 字符设备驱动第六课---ioctl
- linux驱动开发之字符设备--内核和用户空间数据的交换(ioctl)
- 高级字符设备驱动-Ioctl设备控制笔记
- linux高级字符设备驱动(一 设备Ioctl控制)
- 高级字符设备驱动-Ioctl设备控制笔记
- linux设备驱动之Ioctl控制
- POJ1840
- wikioi 1022 覆盖
- DOWS命令收集
- CentOS下sqoop1.4.4的安装
- 关于深度优先和广度优先的问题
- 字符设备之ioctl
- Nginx如何处理一个请求
- CUDA连载
- Power Management
- The process "E:\Qt\4.8.5\bin\qmake.exe" exited with code 2.
- Linux用户环境变量
- PHP开发-分页实现(附效果图)
- ASP.NET利用DOC模板导出Word
- C#中使用进制转换思想对字符串进行任意进制任意字典的加密和解密