当前位置: 首页 > news >正文

Linux下ioctl的应用

文章目录

  • 1、ioctl简介
  • 2、示例程序编写
    • 2.1、应用程序编写
    • 2.2、驱动程序编写
  • 3、ioctl命令的构成
  • 4、测试

1、ioctl简介

ioctl(input/output control)是Linux中的一个系统调用,主要用于设备驱动程序与用户空间应用程序之间进行设备特定的输入/输出操作。它提供了一种通用的机制,允许用户空间的应用程序通过文件描述符与设备进行交互,以执行标准文件操作(如读取、写入、打开和关闭)之外的特殊操作。

2、示例程序编写

本次示例程序包括应用程序和驱动程序。

2.1、应用程序编写

应用程序中,将用户输入的数据通过ioctl()传入到驱动程序,并通过ioctl()读取出来。

/* ioc_test.c */#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>// 定义设备类型和 ioctl 命令
#define IOC_MAGIC  'M'
#define MY_IOCTL_GET_PARAM _IOR(IOC_MAGIC, 0, int)
#define MY_IOCTL_SET_PARAM _IOW(IOC_MAGIC, 1, int)int main() 
{int fd;int param;int getparam;/* 1、打开设备节点 */fd = open("/dev/ioc", O_RDWR);if (fd < 0) {perror("open");return -1;}/* 2、获取用户输入 */  fprintf(stdout, "entry the number : ");scanf("%d", &param);/* 3、写入参数 */if (ioctl(fd, MY_IOCTL_SET_PARAM, &param) < 0) {perror("ioctl");close(fd);return -1;}/* 4、读出参数 */if (ioctl(fd, MY_IOCTL_GET_PARAM, &getparam) < 0) {perror("ioctl");close(fd);return -1;}fprintf(stdout, "getparam = %d\n", getparam);// 关闭文件close(fd);return 0;
}

2.2、驱动程序编写

重点主要有如下两个部分:

1、file_operations中指定ioctl操作函数:

static struct file_operations ioc_drv = {.owner	 = THIS_MODULE,.open    = ioc_drv_open,.read    = ioc_drv_read,.write   = ioc_drv_write,.release = ioc_drv_close,.unlocked_ioctl = my_device_ioctl,
};

2、填充ioctl函数:

#define IOC_MAGIC  'M'
#define MY_IOCTL_GET_PARAM _IOR(IOC_MAGIC, 0, int)
#define MY_IOCTL_SET_PARAM _IOW(IOC_MAGIC, 1, int)static long my_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
{static int param = 0;switch (cmd) {/* 设置参数命令 */case MY_IOCTL_SET_PARAM:printk(KERN_INFO "MY_IOCTL_SET_PARAM\n");if (copy_from_user(&param, (int __user *)arg, sizeof(param))) {return -EFAULT;}printk(KERN_INFO "my_device: set param to %d\n", param);break;/* 读取参数命令 */case MY_IOCTL_GET_PARAM:printk(KERN_INFO "MY_IOCTL_GET_PARAM\n");if (copy_to_user((int __user *)arg, &param, sizeof(param))) {return -EFAULT;}printk(KERN_INFO "my_device: get param %d\n", param);break;default:return -EINVAL; }return 0;
}

3、完整的驱动程序如下:

/* ioc_drv.c */#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>static int major = 0;
static struct class *ioc_class;#define IOC_MAGIC  'M'
#define MY_IOCTL_GET_PARAM _IOR(IOC_MAGIC, 0, int)
#define MY_IOCTL_SET_PARAM _IOW(IOC_MAGIC, 1, int)static long my_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
{static int param = 0;switch (cmd) {case MY_IOCTL_SET_PARAM:printk(KERN_INFO "MY_IOCTL_SET_PARAM\n");if (copy_from_user(&param, (int __user *)arg, sizeof(param))) {return -EFAULT;}printk(KERN_INFO "my_device: set param to %d\n", param);break;case MY_IOCTL_GET_PARAM:printk(KERN_INFO "MY_IOCTL_GET_PARAM\n");if (copy_to_user((int __user *)arg, &param, sizeof(param))) {return -EFAULT;}printk(KERN_INFO "my_device: get param %d\n", param);break;default:return -EINVAL; }return 0;
}static ssize_t ioc_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static ssize_t ioc_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static int ioc_drv_open (struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static int ioc_drv_close (struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}static struct file_operations ioc_drv = {.owner	 = THIS_MODULE,.open    = ioc_drv_open,.read    = ioc_drv_read,.write   = ioc_drv_write,.release = ioc_drv_close,.unlocked_ioctl = my_device_ioctl,
};static int __init ioc_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);major = register_chrdev(0, "ioc", &ioc_drv);ioc_class = class_create(THIS_MODULE, "ioc_class");err = PTR_ERR(ioc_class);if (IS_ERR(ioc_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "ioc");return -1;}device_create(ioc_class, NULL, MKDEV(major, 0), NULL, "ioc"); /* /dev/ioc */return 0;
}static void __exit ioc_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(ioc_class, MKDEV(major, 0));class_destroy(ioc_class);unregister_chrdev(major, "ioc");
}module_init(ioc_init);
module_exit(ioc_exit);MODULE_LICENSE("GPL");

3、ioctl命令的构成

一个完整的ioctl命令码通常包含以下几个字段:

  1. 设备类型(通常是8位):用于标识设备或设备驱动程序的类型。这使得系统能够区分不同的设备或设备组。
  2. 序列号(也是8位):在同一设备类型下,用于区分不同的ioctl命令。每个命令都有一个唯一的序列号,以确保命令的唯一性。
  3. 方向位(2位):指示数据传输的方向。这可以是读操作、写操作或读写操作。方向位帮助设备驱动程序了解用户空间程序期望执行的操作类型。
  4. 数据大小(8~14位):指定用户空间与内核空间之间传输的数据的大小。这确保了数据在传输过程中的完整性和一致性。

在Linux内核中,为了简化ioctl命令的创建过程,提供了一些宏定义。可以看到在上面的应用程序和驱动程序中,都使用了宏来创建ioctl命令:

#define IOC_MAGIC  'M'
#define MY_IOCTL_GET_PARAM _IOR(IOC_MAGIC, 0, int)
#define MY_IOCTL_SET_PARAM _IOW(IOC_MAGIC, 1, int)

可用的宏有如下:

// _IO宏用于创建不带数据传输的ioctl命令
// type是设备类型,通常是一个字符常量,用于区分不同的设备或设备驱动程序
// nr是命令序号,用于在同一设备类型下区分不同的命令
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)// _IOR宏用于创建从设备读取数据的ioctl命令
// type和nr的含义与_IO宏相同
// size是数据类型大小
#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))// _IOW宏用于创建向设备写入数据的ioctl命令
// 其他参数的含义与_IOR宏相同
#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))// _IOWR宏用于创建既读取又写入数据的ioctl命令
// 其他参数的含义与_IOR和_IOW宏相同
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

4、测试

1、编译驱动程序,加载驱动程序。

2、编译应用程序,运行应用程序。

相关文章:

Linux下ioctl的应用

文章目录 1、ioctl简介2、示例程序编写2.1、应用程序编写2.2、驱动程序编写 3、ioctl命令的构成4、测试 1、ioctl简介 ioctl&#xff08;input/output control&#xff09;是Linux中的一个系统调用&#xff0c;主要用于设备驱动程序与用户空间应用程序之间进行设备特定的输入/…...

如何通过 prometheus-operator 实现服务发现

在之前的章节中,我们讲解了如何编写一个自定义的 Exporter,以便将指标暴露给 Prometheus 进行抓取。现在,我们将进一步扩展这个内容,介绍如何使用 prometheus-operator 在 Kubernetes 集群中自动发现并监控这些暴露的指标。 部署应用 在 Kubernetes 集群中部署我们的自定…...

认识HTML的标签结构

一、HTML的基本概念 1.什么是HTML&#xff1f; ①HTML是描述网页的一种标记语言&#xff0c;也被称为超文本标记语言【并不是一种编程语言】 ②HTML包含了HTML标签和文本内容 ③HTML文档也称为web页面 2.HTML的标签 HTML的标签通常成对出现&#xff0c;HTML文档由标签和受…...

MySQL 之INDEX 索引(Index Index of MySQL)

MySQL 之INDEX 索引 1.4 INDEX 索引 1.4.1 索引介绍 索引&#xff1a;是排序的快速查找的特殊数据结构&#xff0c;定义作为查找条件的字段上&#xff0c;又称为键 key&#xff0c;索引通过存储引擎实现。 优点 大大加快数据的检索速度; 创建唯一性索引&#xff0c;保证数…...

基于flask+vue的租房信息可视化系统

✔️本项目利用 python 网络爬虫抓取某租房网站的租房信息&#xff0c;完成数据清洗和结构化&#xff0c;存储到数据库中&#xff0c;搭建web系统对各个市区的租金、房源信息进行展示&#xff0c;根据各种条件对租金进行预测。 1、数据概览 ​ 将爬取到的数据进行展示&#xff…...

开源Web主机控制面板ISPConfig配置DNS

ISPConfig 是一个开源的 Web 主机控制面板&#xff0c;特别适合用于构建虚拟主机环境。 它拥有强大的 DNS 管理功能&#xff0c;可以&#xff1a; 管理 DNS 区域 (主区域、辅助区域)。支持多种记录类型。DNSSEC 支持。远程 DNS 服务器管理。 ISPConfig 优点在于专为主机服务设…...

【Python项目】信息安全领域中语义搜索引擎系统

【Python项目】信息安全领域中语义搜索引擎系统 技术简介&#xff1a;采用Python技术、MYSQL数据库等实现。 系统简介&#xff1a;系统主要是围绕着语义搜索展开的&#xff0c;要将输入的文字在爬取数据时能够通过深层次的内涵理解&#xff0c;来更好的查找到与之相关的精准信息…...

网站搭建基本流程

需求分析&#xff1a; 实现网站搭建的过程&#xff1a;首先进行网站的需求性分析 网站可分为前台系统和后台系统&#xff0c;由不同的功能拆分为不同的模块 如下是一个电商网站可以拆分出的模块&#xff1a; 在编写代码前&#xff0c;我们要先对网站进行架构&#xff0c;通过…...

mysql 存储空间增大解决方案

一&#xff1a;查询数据库中表占比比较多的表 SELECT table_name AS "Tables", round(((data_length index_length) / 1024 / 1024), 2) AS "Size (MB)" FROM information_schema.tables WHERE table_schema "自己的数据库名"; …...

深入解析队列与广度优先搜索(BFS)的算法思想:原理、实现与应用

目录 1. 队列的基本概念 2. 广度优先搜索&#xff08;BFS&#xff09;的基本概念 3. 队列在BFS中的作用 4. BFS的实现细节 5. C实现BFS 6. BFS的应用场景 7. 复杂度分析 8. 总结 1. 队列的基本概念 队列&#xff08;Queue&#xff09;是一种先进先出&#xff08;FIFO, …...

Swap to Gather-----

C - 烟销日出不见人 问题陈述 给定一个长度为 NN 的字符串 SS&#xff0c;由 0 和 1 组成。保证 SS 至少包含一个 1。 您可以执行以下操作任意次数&#xff08;可能为零&#xff09;&#xff1a; 选择一个整数 ii (1≤i≤N−11≤i≤N−1)&#xff0c;并交换 SS 的第 ii 个和…...

使用DeepSeek+本地知识库,尝试从0到1搭建高度定制化工作流(自动化篇)

7.5. 配图生成 目的&#xff1a;由于小红书发布文章要求图文格式&#xff0c;因此在生成文案的基础上&#xff0c;我们还需要生成图文搭配文案进行发布。 原实现思路&#xff1a; 起初我打算使用deepseek的文生图模型Janus进行本地部署生成&#xff0c;参考博客&#xff1a;De…...

Python 函数式编程全攻略:从理论到实战的深度解析

本文深入剖析 Python 函数式编程&#xff0c;详细讲解其概念、核心特性&#xff08;迭代器、生成器等&#xff09;、内置函数及相关模块&#xff08;itertools、functools &#xff09;&#xff0c;结合丰富示例与直观图表&#xff0c;助力读者全面掌握函数式编程技巧&#xff…...

Ollama 在 LangChain 中的使用

文章目录 一、langChain 介绍二、环境安装1.依赖库安装2.下载模型 三、基本使用示例1.使用 ChatPromptTemplate 进行对话2.流式输出3.工具调用4.多模态模型调用 四、进阶使用1.使用 ConversationChain 进行对话2.自定义提示模板3.构建一个简单的 RAG 问答系统 五、遇到问题与解…...

使用apt-rdepends制作软件离线deb安装包

使用apt-rdepends制作软件离线deb安装包 除基础软件外&#xff0c;还要获取软件依赖包。 依赖包工具安装 apt-get install apt-rdependsapt-rdepends工具使用 使用apt-rdepends工具&#xff0c;递归方式分析软件依赖&#xff0c;下载软件包本体&#xff0c;和依赖包。制作时…...

根据POD名称生成 三部曲:get、describe、log、exec

#!/bin/bash# 定义颜色变量 RED\033[0;31m GREEN\033[0;32m YELLOW\033[0;33m NC\033[0m # No Color# 检查是否传入 Pod 名称作为参数 if [ -z "$1" ]; then# 如果没有传参&#xff0c;则提示用户输入 Pod 名称echo -e "${YELLOW}Please enter the Pod name:${…...

SQL sever数据导入导出实验

1.创建数据库TCP-H &#xff08;1&#xff09;右键“数据库”&#xff0c;点击“新建数据库”即可 &#xff08;2&#xff09;用sql语言创建&#xff0c;此处以创建数据库DB_test为例&#xff0c;代码如下&#xff1a; use master;go--检查在当前服务器系统中的所有数据里面…...

python环境的yolov11.rknn物体检测

1.首先是我手里生成的一个yolo11的.rknn模型&#xff1a; 2.比对一下yolov5的模型&#xff1a; 2.1 yolov5模型的后期处理&#xff1a; outputs rknn.inference(inputs[img2], data_format[nhwc])np.save(./onnx_yolov5_0.npy, outputs[0])np.save(./onnx_yolov5_1.npy, outpu…...

I2C、SPI、UART

I2C&#xff1a;串口通信&#xff0c;同步&#xff0c;半双工&#xff0c;双线&#xff08;数据线SDA时钟线SCL&#xff09;&#xff0c;最大距离1米到几米 SPI&#xff08;串行外设接口&#xff09;&#xff1a;串口通信&#xff0c;同步&#xff0c;全双工&#xff0c;四线&…...

如何监控和优化 MySQL 中的慢 SQL

如何监控和优化 MySQL 中的慢 SQL 前言一、什么是慢 SQL&#xff1f;二、如何监控慢 SQL&#xff1f;1. 启用慢查询日志启用方法&#xff1a;日志内容&#xff1a; 2. 使用 mysqldumpslow 分析日志 三、如何分析慢 SQL&#xff1f;1. 使用 EXPLAIN 分析执行计划使用方法&#x…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...