ioctl 详细介绍
来源:互联网 发布:fedora13 yum源 编辑:程序博客网 时间:2024/06/07 10:39
ioctl 详细介绍
(一)ioctl 的作用:
通过设备驱动程序执行各种类型的硬件控制。除了简单数据传输外,大部分设备可以执行其他的一些操作,比如,用户空间经常请求设备锁门、弹出介质、报告错误信息、改变波特率或者执行自破坏等等。
Ioctl的操作通过流程图简言之:
从图1可知,user mode 送command到kernel mode,然后控制硬件。
(二)ioctl的函数模型:
User mode (用户空间):
int ioctl(int fd, unsigned long cmd, …);
其中...省略号表示可变参数,cmd表示指令,fd表示应用程序传递的文件描述符。
Kernel mode (内核空间):
int ( *ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
inode 和filp两个指针的值对应于fd, cmd和user mode cmd相同、arg是附加参数,可以设置为Null或者变量,也可以是指针。
(三) ioctl 的command解析:
Ioctl 的command编号的约定方法:
名称
Type
Number
Direction
size
位数
8bits
8bits
2bits
13/14bits
Type:又称幻数,选择一个号码,并在整个驱动中使用这个号码,这个字段为8bits。
Number:序数(顺序编号)。也为8bits
Direction: 如果command涉及数据传输,则该字段定义数据传输的方向。可以使用的值包括_IOC_NONE(没有数据传输), _IOC_READ(从设备中读取数据),_IOC_WRITE(向设备中传人数据),_IOC_WRITE|_IOC_READ(双向传输数据)。该段占2bits
Size:涉及用户数据的大小,该段占13/14bits
内核定义一些生产command的宏:
_IO()、_IOR(), _IOW, _IOWR.
#define _IOC(dir, type, nr, size) (((dir) <<_IOC_DIRSHIFT) \
|((type) <<_IOC_TYPESHIFT)) \
|((nr) <<_IOC_NRSHIFT) \
|((size)<< _OC_SIZESHIFT))
#define _IO(type, nr) _IOC(_IOC_NONE, type, nr, 0)
#define _IOR(type, nr, size) _IOC(_IOC_READ, (type), (nr), \
(_IOC_TYPECHECKSIZE))
#define _IOW(type, nr, size) _IOC(_IOC_WRITE, (type), (nr), \
(_IOC_TYPECHECKSIZE))
#define _IOWR(type, nr, size) _IOC(_IOC_WRITE |_IOC_READ , (type), (nr), \
(_IOC_TYPECHECKSIZE))
_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd)和_IOC_SIZE(cmd), 这几个宏用于解开位字段的宏。
type是幻数不是类型,其中涉及一些宏在此没有明说,可以参考linux内核docment。
(四)ioctl的返回值:
Ioctl函数的返回值目前有两种版本,其一返回-ENVAL (Invalid argument, 非法参数),因为命令参数确实不合法,所以范围该这是合理的。另一种返回值为-ENTTY(Inappropriate ioctl for device, 不合适的设备ioctl),这看起来更加确切。但实际中,更多的返回-ENVAL。
(五)ioctl 函数kernel mode实现例子
在本例子中假设一种设备device,通过ioctl实现设置、获取device模块的属性值,其设备驱动的ioctl()函数如下:
#define DEVICE_IOC_MAGIC ‘k’
#define DEVICE_IOC_SET _IOW(DEVICE_IOC_MAGIC, 1, int) //int is “size”
#define DEVICE_IOC_GET _IOR(DEVICE_IOC_MAGIC, 2, int)
#define DEVICE_IOC_CLR _IO(DEVICE_IOC_MAGIC,3, int)
#define DEVICE_IOC_MAXNR 5
static int device_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd,
unsigned long arg)
{
int err = 0, temp = 0;
int retval = 0;
/*验证type、number*/
if(_IOC_TYPE(cmd)!= DEVICE_IOC_MAGIC) return –ENOTTY;
if(_IOC_NR(cmd)!= DEVICE_IOC_MAXNR) return –ENOTTY;
/*direction 是一个位掩码,而VERIFY_WRITE用于R/W*传输
*“type”是针对用户空间而言的,而access_ok是面向内核的。因此,“读取”*和“写入”的概念切好相反。*/
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
else if(_IOC_DIR(cmd)&_IOC_WRITE)
err = !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
if(err) return –EFAULT;
switch(cmd){
case DEVICE_IOC_SET:
if(!capable(CAP_SYS_ADMIN))
return –EPERM;
retval = __get_user(device_value, (int __user*arg));
break;
case DEVICE_IOC_GET:
retval = __put_user(device_value, (int __user*)arg);
break;
case DEVICE_IOC_CLR:
memset(device->mem, 0, 512*sizeof(int));
printk(KERN_INFO, “device memory is set to zero\n”);
retval = 1;
break;
default:
return -EINVAL
}
}//end driver_ioctl funtion.
对函数access_ok(),__get_user(),__put_user()的模型说明:
在ioctl函数中,如果附件参数是指针时,该指针指向用户空间时,必须确保指向的用户空间是合法的。对未验证的用户空间指针的访问,可能导致内核oops、系统崩溃或者安全问题。如果用copy_from_user()和copy_to_user()进行用户空间和内核空间的数据传输时,用户空间地址已经得到验证,而对于用__get_user()和__put_user进行用户空间和内核空间的数据传输时,指针指向的地址空间没有进行验证,因此需要用access_ok()函数进行验证。此时会产生一种疑问,为什么不用copy_from_user()和copy_to_user()进行,下文可以获得解释。
access_ok(int type, const void*addr, unsigned long size);
type: 应该是VERIFY_READ或者VERIFY_WRITE,取决于要执行的动作是读取还是写入用户空间内存区。
addr: 用户空间的地址。
size: 字节数目。
Return: 返回一个布尔值:1表示成功,0表示失败。如果返回失败,驱动程序通常返回-EFAULT给调用者。
put_user(datum, ptr)和__put_user(datum, ptr):这宏用于把datum写入到ptr指向的用户空间,其传递的速度比较快,因此传递单个数据时,应该用这个宏而不用copy_to_user()和copy_from_user()。
get_user(local, ptr)和__get_user(local, ptr): 这宏用于从用户空间接受一个数据。接收的数值被保存在局部变量local中,返回值则指明了操作是否成功。因此put_user,__put_user,get_user以及__get_user中ptr指向的用户空间应该被access_ok检验后才使用。
(六)ioctl 函数User mode实现例子
int device_value =0;
ioctl(fd, DEVICE_IOC_SET, &device_value);//set value
ioctl(fd, DEVICE_IOC_GET, &device_value); //get value
ioctl(fd, DEVICE_IOC_CLR ) ;//clear memory
转载请注明出处
- ioctl 详细介绍
- ioctl 详细说明
- ioctl函数详细分析
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl函数详细说明
- ioctl 详细说明
- ioctl函数介绍
- ioctl函数使用方法介绍
- Translater-语言翻译类
- 深入理解linux设备驱动中的阻塞型I/O与非阻塞型I/O
- XmlToJson-xml对象转换为Json对象类
- Vs2008 当切换到图形设计时,处于假死状态的处理方案
- Android Activity 之间切换的各种效果
- ioctl 详细介绍
- StringHelper-字符串辅助类
- 元素水平居中显示方法 CSS
- Chrome 浏览器性能对比测试报告
- RandomHelper-随机数辅助类
- 数据库方言
- VC2010如何给ActiveX添加事件
- 目标5——启动Gii——Yii代码脚手架
- sofamvc