【Linux Device Driver】—(3.1)—ioctl——原理

来源:互联网 发布:网络教育的大专有用吗 编辑:程序博客网 时间:2024/05/16 01:20

大部分驱动除了需要具备读写设备能力外,还需要具备对硬件控制的能力,例如:要求设备报告错误信息改变模特率,这些操作常常通过ioctl方法来实现!

这里的东西看上去的却挺多,但是还是依照此次的原则,只是对自己知识的一个复习,所以也就懒得贴那么多的文字。

 

1、ioctl方法

 

用户空间:

int ioctl(int fd, unsigned long cmd, ...);

原型中的省略号表示这是一个可选的参数,存在与否依赖于控制命令(第2个参数)是否涉及到与设备的数据交互。

 

内核:

#include <linus/fs.h>// 不使用BLK(大内核锁),降使用此种函数指针代替ioctllong (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);// 兼容64位系统,将使用此函数指针代替long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

这里如果cmd命令不涉及数据传输,被驱动操作接收到的arg值是无定义的。

2、ioctl函数定义命令

 

ioctl命令编码被划分为几个段,include/asm/ioctl.h中定义了这些字段:类型(幻数),基数,传送方向,参数大小等。Documentation/ioctl-number.txt文件中罗列了再内核中已经使用的幻数。

 

#include <linus/ioctl.h>/* used to create numbers */#define _IO(type,nr)_IOC(_IOC_NONE,(type),(nr),0)#define _IOR(type,nr,size)_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))#define _IOW(type,nr,size)_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))#define _IOWR(type,nr,size)_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))/* used to decode ioctl numbers.. */#define _IOC_DIR(nr)(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)#define _IOC_TYPE(nr)(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)#define _IOC_NR(nr)(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)#define _IOC_SIZE(nr)(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)


2、ioctl函数定义命令3、ioctl函数的实现

 

(3.1)返回值

ioctl函数的实现通常是根据命令执行的一个switch语句。但是当命令不能匹配任何一个设备所支持的命令时,通常返回-EINVAL(“非法参数”)。

 

(3.2)参数使用

 

如果是一个整数,可以直接使用。如果是指针,我们必须确保这个用户地址是有效的,因此使用前必须要做正确性检查(当然也有不需要检测的,就是前面没有“__”的内核空间和用户空间交互函数)。

 

int access_ok(int type, const void *addr, unsigned long size)

其中第一个参数是VERIFY_READ或者是VERIFY_WRITE,用来表明读用户内存还是写用户内存(千万记住和读写函数对调的!),addr参数是要操作的用户内存地址,size是操作的长度。

access_ok返回一个布尔值:1表示成功和0表示失败(存储有问题),如果该函数返回失败,则ioctl应当返回-EFAULT。

 

 

原创粉丝点击