ioctl()函数的cmd参数是怎样得出的?
① Linux对ioctl()函数的cmd参数有特殊的定义
② 我们来以_IOW为例,看看Linux系统是如何定义_IOW宏的
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
③ 可以看出 cmd在用户程序端由一些宏根据设备类型、序列号、传送方向、数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过switch{case}结构进行相应的操作
④ 因此,在驱动程序和应用程序中必须有相同的关于cmd参数的宏定义,其具体的实例如下:(红色部分)
驱动程序中:
..........
MODULE_AUTHOR("Lw");
MODULE_LICENSE("Dual BSD/GPL");
#define GPIODEV_MAJOR 0
#define GPIODEV_NR_DEVS 9
#define DEVICE_NAME "gpiocdev"
#define GPIO_MAGIC 'k'
#define IOCTL_GPIO_INPUT _IOW(GPIO_MAGIC,1,int)
#define IOCTL_GPIO_OUTPUT _IOW(GPIO_MAGIC,2,int)
static int gpio_ioctl(struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
unsigned int data;
int ret;
ret=copy_from_user(&data,(unsigned int __user *)arg,sizeof(int));
if(ret)
return -EFAULT;
switch(cmd)
{
case IOCTL_GPIO_INPUT: gpio_config(0x0,data); return 0;
case IOCTL_GPIO_OUTPUT: gpio_config(0x55555555,data); return 0;
default:
return -EINVAL;
}
}
.................
应用程序中:
...........
#define GPIO_MAGIC 'k'
#define IOCTL_GPIO_INPUT _IOW(GPIO_MAGIC,1,int)
#define IOCTL_GPIO_OUTPUT _IOW(GPIO_MAGIC,2,int)
int main(int argc,char *argv[])
{
int dev_fd,i,j;
unsigned int write_data;
unsigned int output_no=1;
dev_fd=open("/dev/gpiocdev1",O_RDWR|O_NONBLOCK);
if(dev_fd==-1)
{
printf("Can't open the device gpio\n");
exit(1);
}
ioctl(dev_fd,IOCTL_GPIO_OUTPUT,&output_no);
while(1)
{
for(i=0;i<16;i++)
{
write_data=0xfffffffe;
write_data &=~(i<<5);
write(dev_fd,&write_data,sizeof(write_data));
// sleep(1); //delay 1s
usleep(500000); //delay 500ms
}
}
close(dev_fd);
return 0;
}