转自:http://my.oschina.net/u/274829/blog/285014
1,ioctl介绍
ioctl控制设备读写数据以及关闭等。
用户空间函数原型:int ioctl(int fd,unsinged long cmd,...)
- fd-文件描述符
- cmd-对设备的发出的控制命令
- ...表示这是一个可选的参数,存在与否依赖于cmd,如cmd为修改波特率,那么....就表示波特率的值。如果cmd表示关闭,则不需要参数
内核函数原型
file_operations结构体里面long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
ioctl命令段分为:类型,序号,传递方向,参数大小
- Type 类型:表明哪个设备的命令,在参考了ioctl-number.txt之后选出,8位宽
- Number 序号:表明设备命令中的第几个,8位宽
- Direction 传送方向:可能的值是
_IOC_NONE(没数据传输)
_IOC_READ(从设备读)
_IOC_WRITE
- Size 用户参数大小:(13/14位宽,视处理器而定)
内核提供了一些宏来帮助定义命令:
- _IO(type, nr ) type为命令类型 如int, nr为序号
没有参数的命令
- _IOR(type, nr, datatype)
从驱动中读数据,datatype 读的数据参数的类型
- _IOW(type, nr, datatype)
写数据到驱动
- _IOWR(type,nr, datatype)
读写数据
定义命令例子 #define MEM_IOC_MAGIC ‘m‘ //定义幻数,因为命令类型type是8位的所以找个字符代替
#define MEM_IOCSET
_IOW(MEM_IOC_MAGIC,0,int) //命令 去写 一个 int型的数据
#define MEM_IOCGQSET
_IOR(MEM_IOC_MAGIC, 1, int)
2,ioctl命令使用时注意事项
用户使用int ioctl(int fd,unsinged long cmd,...)时,...就是要传递的参数
再通过long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long arg);中的arg传递,如果arg是一个整形,可以直接使用,如果是指针,我们必须确保这个用户地址是有效的,因此,使用之前需要进行正解的检查。
内部有检查的,不需要检测的:
Copy_from_user
Copy_to_user
Get_user
Put_user
需要检测的:
__get_user
__put_user
使用int access_ok(int type, const void *addr, unsigned long size)检测
Type 是VERIFY_READ 或者VERIFY_WRITE用来表明是读用户内存还是写用户内存。
Addr参数是要操作的用户内存地址,size是操作的长度。如果ioctl需要从用户空间读一个整数,那么size参数就等于sizeof(int)
内核读,写入用户空间,所以用户空间使用VERIFY_WRITE写验证用户内存是否可用。
Access_ok返回一个布尔值:1,是成功(存取没问题),失败,ioctr返回-EFAULT
3,ioctl实现例程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
|
.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
测试程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
1,ioctl介绍ioctl控制设备读写数据以及关闭等。 用户空间函数原型:int ioctl(int fd,unsinged long cmd,...)
内核函数原型 file_operations结构体里面long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); ioctl命令段分为:类型,序号,传递方向,参数大小
_IOC_NONE(没数据传输) _IOC_READ(从设备读) _IOC_WRITE
内核提供了一些宏来帮助定义命令:
从驱动中读数据,datatype 读的数据参数的类型
写数据到驱动
读写数据 定义命令例子 #define MEM_IOC_MAGIC ‘m‘ //定义幻数,因为命令类型type是8位的所以找个字符代替 #define MEM_IOCSET _IOW(MEM_IOC_MAGIC,0,int) //命令 去写 一个 int型的数据 #define MEM_IOCGQSET _IOR(MEM_IOC_MAGIC, 1, int) 2,ioctl命令使用时注意事项 用户使用int ioctl(int fd,unsinged long cmd,...)时,...就是要传递的参数 再通过long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long arg);中的arg传递,如果arg是一个整形,可以直接使用,如果是指针,我们必须确保这个用户地址是有效的,因此,使用之前需要进行正解的检查。 内部有检查的,不需要检测的: Copy_from_user Copy_to_user Get_user Put_user 需要检测的: __get_user __put_user 使用int access_ok(int type, const void *addr, unsigned long size)检测 Type 是VERIFY_READ 或者VERIFY_WRITE用来表明是读用户内存还是写用户内存。 Addr参数是要操作的用户内存地址,size是操作的长度。如果ioctl需要从用户空间读一个整数,那么size参数就等于sizeof(int) 内核读,写入用户空间,所以用户空间使用VERIFY_WRITE写验证用户内存是否可用。 Access_ok返回一个布尔值:1,是成功(存取没问题),失败,ioctr返回-EFAULT 3,ioctl实现例程
.h
Makefile
测试程序
|