引入:
有时对设备不仅仅是进行一些读写操作,还需要进行一些对设备的控制,比如LED的点燃与熄灭,电机的转速等。那就需要使用到ioctl这个系统调用。先来看看他的函数原型:
int ioctl(int fd,unsigned int cmd, ...);
参数:
fd:字符设备文件的文件描述符
cmd:要对设备执行的命令
...:当命令需要参数时填写,不需要则不填写
主要讲一下cmd这个参数。命令从实质上来讲就是一个32位整数,通常这个数会被分为几段分别为类型(也叫幻数,8位)、序号、参数传递方向、参数长度。Linux提供了一些宏来拼接这些数字,规范命令的合理性。例如:
不带参数的命令:_IO(type,nr);
从设备中读:_IOR(type,nr,datatype);
从设备中写:_IOW(type,nr,datatype);
type(幻数)为设备类型,用来区分不同设备;nr为设备序号,区分同种设备的不同个体;datatype读或写数据的类型。
例:
#define MEM_MAGIC ‘m’ //定义幻数
#define MEM_RESTART _IO(MEM_MAGIC,0)
#define MEM_SET _IOW(MEM_MAGIC,0,int)
一般驱动里的ioctl函数通过switch语句实现,范例代码:
1 long mem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 2 { 3 switch(cmd) 4 { 5 case MEM_RESTART: 6 printk("restart device\n"); 7 return 0; 8 case MEM_SET: 9 printk("arg is %d\n",arg); 10 return 0; 11 default: 12 return -EINVAL; 13 } 14 }
用户应用程序调用ioctl的实现方法:
#include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "memdev.h" int main() { int fd; fd = open("/dev/memdev0", O_RDWR); ioctl(fd, MEM_SET,2048); ioctl(fd, MEM_RESTART); return 0; }
memdev.h
#define MEM_MAGIC 'm' #define MEM_RESTART _IO(MEM_MAGIC,0) #define MEM_SET _IOW(MEM_MAGIC,1,int)