ioctl函数中的命令码
ioctl中常用到的两个函数
驱动程序中,ioctl函数作为一个常用的系统调用,进行应用空间与内核空间的数据交换。应用空间与内核空间之间的数据交换,涉及到以下两个常用函数:
将用户空间的数据拷贝到内核空间 : (写)
/**********************************************
*功能:将用户空间的数据拷贝到内核空间
*参数:
* @to 内核空间的地址
* @from 用户空间的地址(虚拟地址)
* @n 拷贝数据的长度(字节)
*返回值: 失败返回没有被拷贝的字节数,成功返回0
*头文件:#include <asm/uaccess.h>
**********************************************/
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
从内核空间拷贝内容到用户空间: (读)
/**********************************************
*功能:从内核空间拷贝内容到用户空间
*参数:
* @to 目标地址,这个地址是用户空间的地址
* @from 源地址,这个地址是内核空间的地址
* @n 拷贝数据的长度(字节)
*返回值: 失败返回没有被拷贝的字节数,成功返回0
*头文件:#include <asm/uaccess.h>
**********************************************/
unsigned long copy_to_user(void *to, const void __user *from, unsigned long n)
ioctl中的命令码cmd
为了保证 cmd 命令的唯一性(类似于现实中的身份证),在头文件:<asm-generic/ioctl.h> 中定义了如下几个宏来获取cmd命令中的域,_IOC_NR()、 _IOC_TYPE()、 _IOC_SIZE()、 _IOC_DIR()
_IOC_NR(cmd) : 读取基数域值 (bit0~ bit7)
_IOC_TYPE(cmd) : 读取魔数域值 (bit8 ~ bit15) 魔数取值在 0x00~0xFF 之间
_IOC_SIZE(cmd) : 读取数据大小域值 (bit16 ~ bit29)
_IOC_DIR(cmd) : 获取读写属性域值 (bit30 ~ bit31)
内核定义了 _IO() , _IOR() , IOW() 和 _IOWR() 这 4 个宏来辅助生成上面的 cmd:
//这几个宏的使用格式为:
_IO (魔数, 基数);
_IOR (魔数, 基数, 变量型)
_IOW (魔数, 基数, 变量型)
_IOWR (魔数, 基数, 变量型 )
//构造无参数的命令编号
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
//构造从驱动程序中读取数据的命令编号
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
//用于向驱动程序写入数据命令
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
//用于双向传输
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
实例:
#define ENABLE_EPIT2 (_IO(0XEF, 0x1)) /* enable epit2 */
#define DISABLE_EPIT2 (_IO(0XEF, 0x2)) /* disable epit2 */
#define SET_EPIT2_VALUE (_IO(0XEF, 0x3)) /* set the value of epit2 */
不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。