static int globalmem_ioctl(struct inode* inodep, struct file* filep,
unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case MEM_CLEAR:
/* 清除全局内存 */
memset(dev->mem, 0, GLOBALMEM_SIZE);
printk(KERN_INFO "globalmem is set to zero\n");
break;
default:
return -EINVAL;//其他不支持的命令
break;
}
return 0;
}
如果设备 A、 B 都支持 0x0、 0x1、 0x2 这样的命令,假设用户本身希望给 A 发 0x1 命令,可是不经意间发给了 B,这个时候 B 因为支持该命令,它就会执行该命令。因此, Linux 内核推荐采用一套统一的 ioctl()命令生成方式。
Linux 系统建议以如图 6.2 所示的方式定义 ioctl()的命令码。
设备类型 | 序列号 | 方向 | 数据尺寸 |
---|---|---|---|
8bit | 8bit | 2bit | 13/14bit |
图 6.2 ioctl()命令码的组成
#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)))
/*_IO、 _IOR 等使用的_IOC 宏*/
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
由此可见,这几个宏的作用是根据传入的 type(设备类型字段)、 nr(序列号字段)和 size(数据长度字段)和宏名隐含的方向字段移位组合生成命令码。
由于 globalmem 的 MEM_CLEAR 命令不涉及数据传输,因此它可以定义如下:
#define GLOBALMEM_MAGIC …
#define MEM_CLEAR _IO(GLOBALMEM_MAGIC,0)