ioctl

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)
  1. cmd组成
  2. 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等等

如果传值就直接取出就行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值