24 ioctl的自定义命令
来源:互联网 发布:在c语言中拆分英文名 编辑:程序博客网 时间:2024/04/29 16:28
系统调用ioctl函数的作用: 用户进程用于通过相应的设备驱动来获取或者设置硬件状态.
ioctl ---> kernel ---> cdev.fops->unlocked_ioctl(...)
在字符设备驱动里, 其中unlock_ioctl函数原形:
long (*unlocked_ioctl) (struct file *fl, unsigned int cmd, unsigned long arg);
cmd参数需要与应用程序调用ioctl时的参数约定,才可以表示一种功能.
cmd的值不能为2,内核里保留此值.
man 2 ioctl_list //可以查看系统里的ioctl关于cmd的参数值
////////////////////////////////////////
在内核里,有提供帮助生成ioctl的cmd的宏(可用,可不用).
cmd是32位的数, 分成以下四个部分:
1). 最高两位表示方向: 读/写/读写(输出/输入/输出输入) 2). 第16位至第29位表示ioctl的第三个参数的大小(unlocked_ioctl的arg). 3). 第8位至第15位表示ioctl命令的类型. 4). 最低8位表示ioctl命令类型里的第几个命令
include/asm-generic/ioctl.h:
'k'_IOC_DIRBITS << 30 | _IOC_SIZEBITS << 16 | _IOC_TYPEBITS << 8 | _IOC_NRBITS#define _IOC_NRBITS 8 //顺序号 0 --- 7#define _IOC_TYPEBITS 8 //类型 8 --- 15#define _IOC_SIZEBITS 14 //ioctl第三个参数的大小 16 --- 29#define _IOC_DIRBITS 2 //方向, 有没有参数, 读/写 30 --- 31///方向位 ////# define _IOC_NONE 0U# define _IOC_WRITE 1U# define _IOC_READ 2U
//////////用于生成一个ioctl的命令的宏定义///#define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT))如:#define LED_ON _IOC(_IOC_WRITE, 'L', 99, 0); //方向, 类型, 第99个命令, ioctl的第三个参数大小为0(即没有第三个参数)//定义一个没有指定方向,没有第三个参数,只指定ioctl命令的类型及命令类型里的序号#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)#define _IOC_TYPECHECK(t) \ ((sizeof(t) == sizeof(t[1]) && \ sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ sizeof(t) : __invalid_size_argument_for_IOC)// 定义一个驱动里输出参数值(用户进程读), 指定ioctl命令的类型及命令类型里的序号及第三个参数的大小#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)))
///////用于获取ioctl命令里方向,类型等信息#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)_IOC_DIR(nr) //获取nr命令里的方向值_IOC_TYPE(nr) //获取nr命令里的类型_IOC_NR(nr) //获取nr命令里的顺序号_IOC_SIZE(nr) //获取nr命令里的第三个参数大小
//////////////////////////////////////////////////////
如led控制的例子, test.c:
#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#include <mach/gpio.h>#include <linux/gpio.h>#include <linux/ioctl.h> //生成ioctl命令的宏定义#define MYMA 1234#define MYMI 3344#define COUNT 1#define LED_IO GPIOA(15)////自定义的ioctl命令////#define LED_MAGIC 0xEF#define LED_ON (_IO(LED_MAGIC, 0x1))#define LED_OFF (_IO(LED_MAGIC, 0x2))dev_t devid; //用于存放设备号struct cdev mycdev; //如有第三个参数,则arg的值为用户进程ioctl调用时传进来的地址long myioctl(struct file *fl, unsigned int cmd, unsigned long arg){ //如果ioctl命令的类型不是LED_MAGIC则退出 if (LED_MAGIC != _IOC_TYPE(cmd)) return -EINVAL; //根据用户进程ioctl的第二个参数值来设置led灯亮或灭 if (LED_ON == cmd) // led on gpio_set_value(LED_IO, 1); else if (LED_OFF == cmd) // led off gpio_set_value(LED_IO, 0); return 0;}struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = myioctl,};static int __init test_init(void){ int ret; devid = MKDEV(MYMA, MYMI); //生成一个设备号 ret = register_chrdev_region(devid, COUNT, "mydev"); if (ret < 0) goto err0; cdev_init(&mycdev, &fops); mycdev.owner = THIS_MODULE; ret = cdev_add(&mycdev, devid, COUNT); if (ret < 0) goto err1; gpio_request(LED_IO, "mydev"); //请求gpio口 gpio_direction_output(LED_IO, 0); //配置gpio口为输出,先输出低电平 return 0;err1: unregister_chrdev_region(devid, COUNT);err0: return ret;}static void __exit test_exit(void){ unregister_chrdev_region(devid, COUNT); cdev_del(&mycdev); gpio_free(LED_IO); //释放gpio}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");
//////////////
app.c:
#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/ioctl.h>////自定义的ioctl命令////#define LED_MAGIC 0xEF#define LED_ON (_IO(LED_MAGIC, 0x1))#define LED_OFF (_IO(LED_MAGIC, 0x2))int main(void){ int fd; fd = open("/dev/mydev", O_RDWR); if (fd < 0) { perror("open dev"); return 1; } while (1) { ioctl(fd, LED_ON); //led灯亮 sleep(1); ioctl(fd, LED_OFF); // led灯灭 sleep(1); } return 0;}
//////////////////////////////////////////////////////////////////////////////////////////
通过ioctl获取烟雾传感器的例子:
test.c
#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>#include <mach/gpio.h>#include <linux/gpio.h>#include <linux/ioctl.h> //生成ioctl命令的宏定义#define MYMA 1234#define MYMI 3344#define COUNT 1//烟雾传感器接在PA(7), 感应到烟雾时输出低电平,正常高电平#define DETECT_IO GPIOA(7)////自定义的ioctl命令////#define DETECTOR_MAGIC 0xAF#define DETECT_RET (_IOR(DETECTOR_MAGIC, 0x1, int))dev_t devid; //用于存放设备号struct cdev mycdev; //如有第三个参数,则arg的值为用户进程ioctl调用时传进来的地址long myioctl(struct file *fl, unsigned int cmd, unsigned long arg){ if (DETECTOR_MAGIC != _IOC_TYPE(cmd)) return -EINVAL; if (DETECT_RET == cmd) *(int *)arg = gpio_get_value(DETECT_IO); return 0; //返回值表示操作是成功与否}struct file_operations fops = { .owner = THIS_MODULE, .unlocked_ioctl = myioctl,};static int __init test_init(void){ int ret; devid = MKDEV(MYMA, MYMI); //生成一个设备号 ret = register_chrdev_region(devid, COUNT, "mydev"); if (ret < 0) goto err0; cdev_init(&mycdev, &fops); mycdev.owner = THIS_MODULE; ret = cdev_add(&mycdev, devid, COUNT); if (ret < 0) goto err1; gpio_request(DETECT_IO, "mydev"); //请求gpio口 gpio_direction_input(DETECT_IO); //配置gpio口为输入 return 0;err1: unregister_chrdev_region(devid, COUNT);err0: return ret;}static void __exit test_exit(void){ unregister_chrdev_region(devid, COUNT); cdev_del(&mycdev); gpio_free(DETECT_IO); //释放gpio}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");
///////////
app.c
#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/ioctl.h>////自定义的ioctl命令////#define DETECTOR_MAGIC 0xAF#define DETECT_RET (_IOR(DETECTOR_MAGIC, 0x1, int))int main(void){ int fd, ret, val; fd = open("/dev/mydev", O_RDWR); if (fd < 0) { perror("open dev"); return 1; } while (1) { ret = ioctl(fd, DETECT_RET, &val); if (ret < 0) break; if (!val) //有烟雾感应到了 { printf("smoke detected ...\n"); break; } } close(fd); return 0;}
阅读全文
0 0
- 24 ioctl的自定义命令
- v412的ioctl命令
- ioctl函数用的命令
- ioctl 命令
- 使用ioctl“实现”自定义的系统调用
- 关于构造IOCTL命令的学习心得
- 带Ioctl命令的字符设备驱动程序
- 关于构造IOCTL命令的学习心得
- 关于构造IOCTL命令的学习心得
- 构造IOCTL命令的学习心得-----_IO,…
- 关于构造IOCTL命令的方法
- linux设备驱动的ioctl命令定义
- 关于构造IOCTL命令的学习心得
- 关于构造IOCTL命令的学习心得
- 关于构造IOCTL命令的学习心得
- [转] ioctl的命令cmd构造详解
- ioctl的命令cmd构造详解
- ioctl参数命令设置
- <cmath>头文件
- Java 8 LocalDate和LocatTime使用
- 图片的稀疏字典学习
- bowtie和samtools在tophat中的使用
- 数据记录
- 24 ioctl的自定义命令
- |算法讨论|RMQ 学习笔记
- [P1297]网线切割
- ubuntu 16.04 server -- 无法进入图形桌面解决办法
- J2SE系列之递归
- 用户注册的ajax请求
- mysql之 mysql 5.6不停机主从搭建(一主一从基于GTID复制)
- Java迭代器Iterator原理和使用总结
- 学习淘淘商城第九十三课(用户登录的实现)