Linux驱动学习—ioctl接口

1、unlock_ioctl和ioctl有什么区别?

kernel 2.6.36 中已经完全删除了struct file_operations 中的ioctl 函数指针,取而代之的是unlocked_ioctl 。ioctl是老的内核版本中的驱动API,unlock_ioctl是当下常用的驱动API。unlocked_ioctl 实际上取代了用了很久的ioctl,主要的改进就是不再需要上大内核锁(BKL) (调用之前不再先调用lock_kernel()然后再unlock_kernel())。

2、unlock_ioctl和read/write函数有什么相同点和不同点

相同点:都可以往内核里面写数据。

不同点:read函数只能完成读的功能,write只能完成写的功能。读取大数据的时候效率高。ioctrl既可以读也可以写。读取大数据的时候效率不高。

3、unlock_ioctl接口命令规则

第一个分区:0-7位,命令的编号,范围是0-255。

第二个分区:8-15位,命令的幻数。

注意:第一个分区个第二个分布主要作用是用来区分命令的。

第三个分区:16-29位表示传递的数据大小。

第四个分区:30-31位代表读写的方向。

00:表示用户程序和驱动程序没有数据传递。
10:表示用户程序从驱动里面读数据。
01:表示用户程序向驱动里面写数据。
11:表示先写数据到驱动里面,然后在从驱动里面把数据读出来。

这四个分区的示例图如下:

img

4、命令的合成宏与分解宏

4.1 合成宏

在include\uapi\asm-generic\ioctl.h

#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)))
注释如下:
_IO(type,nr)用来定义没有数据传递的命令
_IOR(type,nr,size)用来定义从驱动中读取数据的命令
IOW(type,nr,size)用来定义从驱动中写入数据的命令
_IOWR(type,nr,size)用来定义输一局交换类型的命令,先写入数据,在读取数据这类命令。
参数:
type:表示命令的组成的魔数,也就是8-15位。
nr:表示命令组成的编号,也就是0-7位。
size:表示命令组成的参数传递大小,注意这里不是传递数字,而是传递数据类型,如要传递4字节,就可以写成int.

4.2 分解宏

#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)是分解命令的方向,也就是上面说30-31位的值。
_IOC_TYPE(nr)分解命令的魔数,也就是上面说的8-15位的值。
_IOC_NR(nr)分解命令的编号,也就是上面说的0-7位。
_IOC_SIZE(nr)分解命令的复制数据大小,也就是上面说的16-29位。
参数说明:
nr:要分解的命令

5、实验:在应用层使用命令合成宏和命令分解宏

值得注意的是,内核中使用的合成宏和分解宏与应用层使用的是一样的。其实可以用户和内核空间共用的头文件,里面是ioctl命令的构成和头文件。但本实例在应用层演示其使用,所以就不定义共用的头文件了。

#incldue <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
​
#define CMD_TEST0 _IO("L",0)
#define CMD_TEST1 _IO("A",1)
#define CMD_TEST2 _IOW("L",2,int)
#define CMD_TEST3 _IOR("L",3,int)
​
int main(int argc, char *argv[])
{printf("30-31 is %d\n",_IOC_DIR(CMD_TEST0));printf("30-31 is %d\n",_IOC_DIR(CMD_TEST3));printf("8-15 is %d\n",_IOC_TYPE(CMD_TEST0));printf("8-15 is %d\n",_IOC_TYPE(CMD_TEST1));printf("0-7 is %d\n",_IOC_NR(CMD_TEST2));
}

6、实验:驱动层和应用层使用ioctl

6.1 驱动层代码

#include <linux/init.h>
#include <linux/module.h>//最基本的文件,支持动态添加和卸载模块
#include <linux/miscdevice.h>//注册杂项设备头文件
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
​
#define CMD_TEST0 _IO("L",0)
#define CMD_TEST1 _IO("A",1)
#define CMD_TEST2 _IOW("L",2,int)
#define CMD_TEST3 _IOW("L",3,int)
#define CMD_TEST4 _IOR("L",4,int)
​
ssize_t misc_read(struct file *file,char __user *ubuf, size_t size, loff_t *loff_t)
{char kbuf[64] = "heheh";if(copy_to_user(ubuf, kbuf, strlen(kbuf)) != 0) {printk("copy_to_user error\n");return -1;}return 0;
}
​
ssize_t misc_wirie(struct file *file,char __user *ubuf, size_t size, loff_t *loff_t)
{char kbuf[64] = {0};if(copy_form_user(kbuf, ubuf, strlen(kbuf)) != 0) {printk("copy_form_user error\n");return -1;}printk("kbuf is %s\n",kbuf);return 0;
}
​
int misc_open(struct inode *inode, struct file *file)
{printk("misc_open \n");return 0;
}
​
int misc_release(struct inode *inode, struct file *file)
{printk("misc_release \n");return 0;
}
​
long misc_ioctl(struct file *file, unsigned int cmd, unsigned long value)
{int val = 0;switch(cmd){case CMD_TEST2:printk("LEN ON!\n");printk("value is %d!!\n",value);break;case CMD_TEST3:printk("LEN OFF!\n");printk("value is %d!!\n",value);break;case CMD_TEST4:val = 12;if(copy_to_user((int *)value, &val, sizeof(val)) != 0) {printk("copy_to_user error\n");return -1;}break;  }
}
struct file_operations misc_fops={.owner = THIS_MODULE,//owner 指针指向的就是你的模块.open  = misc_open,.release = misc_release,.read   = misc_read,.write  = misc_write,.unlocked_ioctrl = misc_ioctl 
};struct miscdevice misc_dev={.minor=MISC_DYNAMIC_MINOR,//MISC_DYNAMIC_MINOR动态分配次设备号.name = "hello_misc",.fops = &misc_fops,
};
​
static int misc_init(void)
{int ret;ret = misc_register(&misc_dev);if(ret < 0){printk("misc register is error \n");return ret;}printk("misc register is succeed \n");return 0;
}
​
static void misc_exit(void)
{misc_deregister(&misc_dev);printk("misc_exit \n");
}
​
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");

6.2应用层ioctl函数

和open read write函数同理,当在应用层代码中调用ioctl接口的时候,其实调用的内核file_operations的unlocked_ioctl结构体成员。

#include <sys/ioctl.h> 
int ioctl(int fd, int cmd, ...) ;
参数1:设备描述符
参数2:指令,如某一个命令对应驱动层的某一个功能
参数3:可变参数,跟命令有关,传递进入驱动层的参数或者是接收数据的缓存
返回值:成功:返回 0,失败:返回 -1,并设置全局变量 errorno 值

6.3应用层代码

#incldue <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
​
#define CMD_TEST0 _IO("L",0)
#define CMD_TEST1 _IO("A",1)
#define CMD_TEST2 _IOW("L",2,int)
#define CMD_TEST3 _IOW("L",3,int)
#define CMD_TEST4 _IOR("L",4,int)
​
int main(int argc, char *argv[])
{int fd; fd = open("/dev/hello_misc",O_RDWR);if (fd < 0) {perror("open error");return fd;}while (1) {ioctl(fd,CMD_TEST2,0);sleep(2);ioctl(fd,CMD_TEST3,1);sleep(2);}return 0;
}

6.4 修改应用层代码,使得用到宏IOR

#incldue <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
​
#define CMD_TEST0 _IO("L",0)
#define CMD_TEST1 _IO("A",1)
#define CMD_TEST2 _IOW("L",2,int)
#define CMD_TEST3 _IOW("L",3,int)
#define CMD_TEST4 _IOR("L",4,int)
​
int main(int argc, char *argv[])
{int fd; fd = open("/dev/hello_misc",O_RDWR);if (fd < 0) {perror("open error");return fd;}while (1) {ioctl(fd,CMD_TEST4,&value);printf("value is %d\n",value);sleep(2);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/599654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【排序算法总结】

目录 1. 稳点与非稳定排序2. 冒泡排序3. 简单选择排序4. 直接插入排序5. 快排6. 堆排7. 归并 1. 稳点与非稳定排序 不稳定的&#xff1a;快排、堆排、选择原地排序&#xff1a;快排也是非原地排序&#xff1a;归并 和三个线性时间排序&#xff1a;桶排序 &#xff0c;计数&…

【经验】VSCode连接远程服务器(可以使用git管理、方便查看和编辑Linux源码)

1、查看OpenSSH Windows10通常自带OpenSSH不需要安装。 Windows10下检查是否已经安装OpenSSH的方法: 1)按下快捷键Win + X,选择Windows PoweShell(管理员) 2)输入以下指令: Get-WindowsCapability -Online | ? Name -like ‘OpenSSH*’ 3)如果电脑未安装OpenSSH,…

基于萤火虫算法优化的Elman神经网络数据预测 - 附代码

基于萤火虫算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于萤火虫算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于萤火虫优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#x…

安科瑞新能源汽车车充电桩有序充电——安科瑞 顾烊宇

要&#xff1a;随着当前经济的不断发展&#xff0c;国家的科技也有了飞速的进步&#xff0c;传统的燃油汽车已经不能适应当前社会的发展&#xff0c;不仅对能源造成巨大的消耗&#xff0c;还对环境造成了污染&#xff0c;当前一种新型的交通运输工具正在占领汽车市场。新能源汽…

物理与网络安全

物流环境安全 场地选择考虑抗震、承重、防火、防水、供电、空气调节、电磁防护、雷击及静电 场地因素&#xff1a; 自然灾害&#xff0c;社会因素&#xff08;加油站、化工厂&#xff09;&#xff0c;配套条件&#xff08;消防&#xff0c;交通&#xff0c;电力&#xff0c;…

爬虫实战3-js逆向入门:以黑猫投诉平台为例

目录 引言 逆向过程 步骤一&#xff1a;找到参数对应js代码位置 步骤二&#xff1a;分析参数值的生成逻辑 步骤三&#xff1a;确定函数u的具体内容 步骤四&#xff1a;使用python实现请求参数的生成 投诉信息爬取 引言 下面是一张主流网页加密方法的思维导图&#xff0c…

算法每日一题:统计重复个数 | 字符串

大家好&#xff0c;我是星恒 感觉好难呀呀呀&#xff01;今天是一道困难题目&#xff0c;思路挺简单&#xff0c;但是有些细节点不是很容易想通&#xff0c;建议大家多画图试一试&#xff0c;这样就会好理解许多 题目&#xff1a;leetcode 466定义 str [s, n] 表示 str 由 n 个…

OpenHarmony之消息机制实现

OpenHarmony之消息机制实现 背景 在之前的介绍&#xff08;OpenHarmony之HDF驱动框架&#xff09;中&#xff0c;了解到OpenHarmony的消息机制主要有以下两种&#xff1a; 用户态应用发送消息到驱动。用户态应用接收驱动主动上报事件。 下面我们分别来看看两种机制用户态的…

23 导航栏

效果演示 实现了一个响应式的导航栏&#xff0c;当鼠标悬停在导航栏上的某个选项上时&#xff0c;对应的横条会从左到右地移动&#xff0c;从而实现了导航栏的动态效果。 Code <div class"flex"><ul><li>1</li><li>2</li><l…

第三部分使用脚手架:vue学习(61-65)

文章目录 61 创建vue脚手架![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f71d4324be0542209e690ab9e886d199.png)62 分析脚手架结构63 render函数64 修改默认配置65 ref 属性 61 创建vue脚手架 写完vue文件&#xff0c;没有脚手架做翻译&#xff0c;浏览器不认识…

基于引力搜索算法优化的Elman神经网络数据预测 - 附代码

基于引力搜索算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于引力搜索算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于引力搜索优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&…

计算机网络学习笔记(一)

文章目录 1.1 请介绍七层网络体系结构。2 .请介绍五层网络体系结构。3 .了解网络编程协议吗&#xff1f;客户端发送给服务器的请求&#xff0c;怎么确定具体的协议&#xff1f;4. TCP、HTTP、FTP分别属于哪一层&#xff1f;5. 讲一下TCP/IP协议。6 .说一说你对ARP协议的理解。7…

基于闪电搜索算法优化的Elman神经网络数据预测 - 附代码

基于闪电搜索算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于闪电搜索算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于闪电搜索优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&…

机器学习实践

1.波士顿房价预测 波士顿房屋的数据于1978年开始统计&#xff0c;共506个数据点&#xff0c;涵盖了波士顿不同郊区房屋的14种特征信息。 在这里&#xff0c;选取房屋价格&#xff08;MEDV&#xff09;、每个房屋的房间数量&#xff08;RM&#xff09;两个变量进行回归&#xff…

解决报错Exception encountered during context initialization

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读报错解决 报错 今天在测试一个类时&#xff0c;突然间报了以下错误。 juni…

vmware安装centos 7.6 操作系统

vmware安装centos 7.6 操作系统 1、下载centos 7.6 操作系统镜像文件2、安装centos 7.6操作系统3、配置centos 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载centos 7.6 操作系统镜像文件 这里选择 2018年10月发布的 7.6 版本 官方下载链…

vscode安装Prettier插件,对vue3项目进行格式化

之前vscode因为安装了Vue Language Features (Volar)插件&#xff0c;导致Prettier格式化失效&#xff0c;今天有空&#xff0c;又重新设置了一下 1. 插件要先安装上 2. 打开settings.json {"editor.defaultFormatter": "esbenp.prettier-vscode","…

【物联网】手把手完整实现STM32+ESP8266+MQTT+阿里云+APP应用——第3节-云产品流转配置

&#x1f31f;博主领域&#xff1a;嵌入式领域&人工智能&软件开发 本节目标&#xff1a;本节目标是进行云产品流转配置为后面实际的手机APP的接入做铺垫。云产品流转配置的目的是为了后面能够让后面实际做出来的手机APP可以控制STM32/MCU&#xff0c;STM32/MCU可以将数…

前缀和算法模板

一维前缀和 算法用途&#xff1a;快速求出数组中某一连续区间的和 一维前缀和算法模板 1、预处理出一个 dp 数组 要求原数组存储在 n 1 的空间大小中&#xff0c;其中后 n 个空间存数据。 dp数组&#xff0c;数组开 n 1个空间&#xff0c;dp[i] 表示 [ 1, i ] 区间内所有…

抖店如何高效率起店?从0到1的起店思路和心得,分享如下!

我是王路飞。 万事开头难&#xff0c;我为什么一直强调让新手商家先入门&#xff0c;把流程跑通呢&#xff1f; 就好像我们上学时候考试&#xff0c;都知道100分很难&#xff0c;那我们就先从60分开始好了&#xff0c;有了考60分的基础&#xff0c;你就知道你跟100分的差距在…