ioctrl
一,作用/与read和write的区别
ioctl同read和write的区别*是:
ioctl一般是用来传递控制参数的,比如:串口的波特率、串口的流控方法(xon/xoff、DTR/DSR、RTS/CTS)等等,一般不
用来传递“主要的”数据,一般用put_user/get_user传递单个数据,不用copy_from_user与copy_to_user*
二,函数原型与cmd组成与配置
long xxx_ioctl (struct file *filep, unsigned int cmd, unsigned long arg)
- cmd组成
- cmd配置
三,编写驱动
1.编写cmd配置文件,设置相应宏定义
#ifndef _PWM_H
#define _PWM_H
#define DEV_FIFO_TYPE 'k'//配置幻数为'k'
#define DEV_FIFO_CLEAN _IO(DEV_FIFO_TYPE,0)
#define DEV_FIFO_GETVALUE _IOR(DEV_FIFO_TYPE,1,int)
#define DEV_FIFO_SETVALUE _IOW(DEV_FIFO_TYPE,2,int)//中间哪个nr可以随便给,不是说write就是2
#endif
2.驱动ioctrl
static int knum = 99;
long hello_ioctl (struct file *filep, unsigned int cmd, unsigned long arg)
{
long err,ret;
void __user *argp = (void __user *)arg;//强制转化为void __user *指针(__user表示在用户空间),非指针变量也能强转为指针变量
int __user *p = argp;//根据具体类型转化为具体指针
if(_IOC_TYPE(cmd)!=DEV_FIFO_TYPE){//判断命令的幻数是否正确
pr_err("cmd %u,bad magic 0x%x/0x%x.\n",cmd,_IOC_TYPE(cmd),DEV_FIFO_TYPE);
return-ENOTTY;
}
if(_IOC_DIR(cmd)&_IOC_READ)//判断命令的方向
ret=!access_ok(VERIFY_WRITE,(void __user*)arg,_IOC_SIZE(cmd));//access_ok用于检查用户传入的指针是否可用
else if( _IOC_DIR(cmd)&_IOC_WRITE )
ret=!access_ok(VERIFY_READ,(void __user*)arg,_IOC_SIZE(cmd));
if(ret){
pr_err("bad access %ld.\n",ret);
return-EFAULT;
}
switch(cmd)//根据不同命令执行不同操作
{
case DEV_FIFO_CLEAN:
printk("DEV_FIFO_CLEAN\n");
break;
case DEV_FIFO_GETVALUE:
err = put_user(knum, p);//传递当个数据到用户空间
printk("DEV_FIFO_GETVALUE %d\n",knum);
break;
case DEV_FIFO_SETVALUE:
err = get_user(knum, p);
printk("DEV_FIFO_SETVALUE %d\n",knum);
break;
default:
return -EINVAL;
}
return err;
}
3.test.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>//这个别忘记加
#include "beep.h"
main()
{
int fd;
int len;
int num;
int ret;
fd = open("/dev/hellodev",O_RDWR);
if(fd<0)
{
perror("open fail \n");
return;
}
ioctl(fd,DEV_FIFO_CLEAN);
ret = ioctl(fd,DEV_FIFO_GETVALUE,NULL);
if(ret < 0)
{
perror("ioctl");
return;
}
printf("num = %d \n",num);
num = 77;
ioctl(fd,DEV_FIFO_SETVALUE,&num);
close(fd);
}
对于ioctl我感觉还是很多不懂
实验得出的结论
1.nr可以随便设置,不是说_Io就是0,_ior就是1
2.arg在test既可以传地址也可以直接传一个值(要求是整形)
这样如果传地址,在驱动就要判断地址有效性还要get_user等等
如果传值就直接取出就行。
octl我感觉还是很多不懂
实验得出的结论
1.nr可以随便设置,不是说_Io就是0,_ior就是1
2.arg在test既可以传地址也可以直接传一个值(要求是整形)
这样如果传地址,在驱动就要判断地址有效性还要get_user等等
如果传值就直接取出就行。