字符设备控制
在用户空间,使用ioctl系统调用来控制设备,原型如下:
intioctl(int fd,unsigned long cmd,...)
ioctl驱动方法有和用户空间版本不用的原型
int(*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned longarg)
structfile:在Linux系统中,每一个打开的文件,在内核中都会关联一个struct file ,它由内核在打开文件时创建,在文件关闭后释放。
structinode:每一个存在于文件系统里面的文件都会关联一个inode结构,该结构主要用来记录文件物理上的信息。
ioctl实现
1、 定义命令
2、 实现命令
定义命令
命令实质是一个整数,通常分为几个段:类型(8位)、序号,参数传递方向,参数长度。
Type(类型):表明这是属于哪个设备的命令。
Number(序号):用来区分同一设备的不同命令。
Direction(参数传递方向):可能的值_IOC_NONE,_IO_READ,_IO_WRITE。
Size:参数长度
Linux系统提供了下面的宏来帮助定义命令:
_IO(type,nr):不带参数的命令
_IOR(type ,nr ,datatype):从驱动中读数据
_IOW(type ,nr ,datatype):写数据到驱动
_IOWR(type ,nr ,datatype):双向传送,tyoe和number成员作为参数被传递
例:#defineMEM_IOC_MAGIC ‘m’ //定义幻数
#define MEM_IOCSET
_IOW(MEM_IOC_MAGIC, 0, int)
#define MEM_IOCGQSET
_IOR(MEM_IOC_MAGIC, 1, int)
实现命令
实现命令包括如下3个技术环节
1、 返回值
2、 参数使用
3、 命令操作
代码示例
/*IO操作*/
int memdev_ioctl(struct inode *inode,struct file *filp,
unsigned int cmd, unsignedlong arg)
{
int err = 0;
int ret = 0;
intioarg = 0;
/* 检测命令的有效性 */
if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC)
return -EINVAL;
if (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR)
return -EINVAL;
/* 根据命令类型,检测参数空间是否可以访问 */
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
if (err)
return -EFAULT;
/* 根据命令,执行相应的操作 */
switch(cmd) {
/* 打印当前设备信息 */
case MEMDEV_IOCPRINT:
printk("<--- CMDMEMDEV_IOCPRINT Done--->\n\n");
break;
/* 获取参数 */
case MEMDEV_IOCGETDATA:
ioarg = 1101;
ret = __put_user(ioarg, (int *)arg);
break;
/* 设置参数 */
case MEMDEV_IOCSETDATA:
ret = __get_user(ioarg, (int *)arg);
printk("<--- In Kernel MEMDEV_IOCSETDATA ioarg = %d--->\n\n",ioarg);
break;
default:
return -EINVAL;
}
return ret;
}