#include
int ioctl(int fd, unsigned long request, ...);
/*
fd:文件描述符
cmd:控制命令
...:可选参数:插入*argp,具体内容依赖于cmd
*/
//使用例子,framerbuffer技术获取屏幕属性
ioctl(fd, FBIOGET_VSCREENINFO, &varInfo);
#include
int (*ioctl) (struct inode *, struct file *, unsigned int cmd, unsigned long argv);
long (*unlocked_ioctl) (struct file *, unsigned int cmd, unsigned long argv);
long (*compat_ioctl) (struct file *, unsigned int cmd, unsigned long argv);
/*
inode file:文件描述符
cmd:由用户空间直接不经修改的传递给驱动程序
argv:可选参数:具体内容依赖于cmd
*/
用户空间的ioctl
会调用内核空间的ioctl
,内核空间中cmd
有具体的含义。
图片转自知乎,侵删。
分为4个字段:数据方向,数据大小,设备类型,命令编号
在驱动编程中通常使用宏定义制造出这个32位的cmd
或者反向解析
#include
/* 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 them.. */
#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)
内核空间示例代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct led_info {
int age;
char stat;
};
#define LED_ON _IOWR('l', 0, struct led_info)
#define LED_OFF _IOWR('l', 1, struct led_info)
#define GET_INFO _IOWR('l', 2, struct led_info)
#define PUT_INFO _IOWR('l', 3, struct led_info)
struct led_info info = {
.age = 0,
.stat = 0,
};
static long led_ioctl(struct file *file, unsigned int cmd, unsigned long argv)
{
int ret = -1;
switch (cmd)
{
case LED_ON:
led_on();
break;
case LED_OFF:
led_off();
break;
case GET_INFO:
ret = copy_to_user((struct led_info*)argv, &info, sizeof(info));
break;
case PUT_INFO:
ret = copy_from_user(&info, (struct led_info*)argv, sizeof(info));
printk("info.age = %d\n", info.age);
break;
}
return 0;
}
用户空间示例代码:
#include
#include
#include
#include
#include
#include
#include
struct led_info {
int age;
char stat;
};
#define LED_ON _IOWR('l', 0, struct led_info)
#define LED_OFF _IOWR('l', 1, struct led_info)
#define GET_INFO _IOWR('l', 2, struct led_info)
#define PUT_INFO _IOWR('l', 3, struct led_info)
int main(int argc, const char *argv[])
{
char stat[4];
struct led_info info;
memset(&info, 0, sizeof(info));
int fd = open("/dev/myled", O_RDWR);
if (fd < 0)
{
perror("open led fail:");
exit(-1);
}
ioctl(fd, GET_INFO, &info);
printf("user info.age = %d\n", info.age);
info.age = 100;
ioctl(fd, PUT_INFO, &info);
close(fd);
return 0;
}
只是对ioctl内核态到用户态的数据传输的测试,实际工程中会对cmd
的各个域进行判断。