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

Linux内核 -- 字符设备之read write poll基本实现

Linux字符设备:read、write和poll函数实现及完整代码

1. read函数

原型

ssize_t read(struct file *file, char __user *buf, size_t count, loff_t *pos);

实现步骤

  1. 检查用户缓冲区:使用copy_to_user将数据从内核空间复制到用户空间。
  2. 返回已读取的字节数:
    • 如果数据长度少于请求长度,返回实际读取的字节数。
    • 如果到达文件末尾,返回0

注意事项

  • 确保对用户缓冲区的访问是安全的。
  • 返回值必须是已成功读取的字节数或错误码(如-EFAULT)。
  • 考虑多线程情况下的并发访问,适当加锁。

示例代码

static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{char data[] = "Hello, World!\n";size_t datalen = strlen(data);if (*pos >= datalen)return 0;if (count > datalen - *pos)count = datalen - *pos;if (copy_to_user(buf, data + *pos, count))return -EFAULT;*pos += count;return count;
}

2. write函数

原型

ssize_t write(struct file *file, const char __user *buf, size_t count, loff_t *pos);

实现步骤

  1. 验证用户数据:使用copy_from_user将数据从用户空间复制到内核空间。
  2. 处理写入数据:通常会将数据存储到设备的内存区域或触发硬件操作。

注意事项

  • 确保处理的是合法数据。
  • 如果设备有缓冲区,需检查空间是否足够。
  • 同样需要考虑多线程并发访问的问题。

示例代码

static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{char kernel_buf[128];if (count > sizeof(kernel_buf) - 1)count = sizeof(kernel_buf) - 1;if (copy_from_user(kernel_buf, buf, count))return -EFAULT;kernel_buf[count] = '\0';printk(KERN_INFO "Received from user: %s\n", kernel_buf);*pos += count;return count;
}

3. poll函数

原型

unsigned int poll(struct file *file, struct poll_table_struct *wait);

实现步骤

  1. 注册等待队列:使用poll_wait将设备的等待队列添加到wait
  2. 返回设备状态:返回一个位掩码,指示设备的可读性、可写性等状态。

注意事项

  • 确保等待队列正确唤醒。
  • 返回值可以是POLLIN(可读)、POLLOUT(可写)等。
  • 处理阻塞和非阻塞模式。

示例代码

static unsigned int my_poll(struct file *file, struct poll_table_struct *wait)
{unsigned int mask = 0;poll_wait(file, &my_wait_queue, wait);if (data_available)mask |= POLLIN | POLLRDNORM; // 可读if (space_available)mask |= POLLOUT | POLLWRNORM; // 可写return mask;
}

4. 完整代码示例

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/sched.h>#define DEVICE_NAME "my_device"
#define BUFFER_SIZE 128static int major;
static char device_buffer[BUFFER_SIZE];
static size_t buffer_len = 0;static wait_queue_head_t my_wait_queue; // 声明等待队列
static int data_available = 0;         // 标志:是否有数据可供读取// read 实现
static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{if (buffer_len == 0) {if (file->f_flags & O_NONBLOCK)return -EAGAIN;// 等待数据可用wait_event_interruptible(my_wait_queue, data_available);if (buffer_len == 0) // 防止被中断唤醒但没有数据return -EINTR;}if (count > buffer_len)count = buffer_len;if (copy_to_user(buf, device_buffer, count))return -EFAULT;buffer_len = 0; // 数据被读取后清空缓冲区data_available = 0;return count;
}// write 实现
static ssize_t my_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{if (count > BUFFER_SIZE - 1)count = BUFFER_SIZE - 1;if (copy_from_user(device_buffer, buf, count))return -EFAULT;device_buffer[count] = '\0';buffer_len = count;// 数据写入后唤醒等待的进程data_available = 1;wake_up_interruptible(&my_wait_queue);return count;
}// poll 实现
static unsigned int my_poll(struct file *file, struct poll_table_struct *wait)
{unsigned int mask = 0;poll_wait(file, &my_wait_queue, wait);if (buffer_len > 0)mask |= POLLIN | POLLRDNORM; // 数据可读if (buffer_len < BUFFER_SIZE)mask |= POLLOUT | POLLWRNORM; // 可写入更多数据return mask;
}// 文件操作结构
static struct file_operations my_fops = {.owner = THIS_MODULE,.read = my_read,.write = my_write,.poll = my_poll,
};// 模块初始化
static int __init my_init(void)
{major = register_chrdev(0, DEVICE_NAME, &my_fops);if (major < 0) {printk(KERN_ALERT "Failed to register character device\n");return major;}init_waitqueue_head(&my_wait_queue); // 初始化等待队列printk(KERN_INFO "Device registered with major number %d\n", major);return 0;
}// 模块退出
static void __exit my_exit(void)
{unregister_chrdev(major, DEVICE_NAME);printk(KERN_INFO "Device unregistered\n");
}module_init(my_init);
module_exit(my_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device with wait queue.");

相关文章:

Linux内核 -- 字符设备之read write poll基本实现

Linux字符设备&#xff1a;read、write和poll函数实现及完整代码 1. read函数 原型 ssize_t read(struct file *file, char __user *buf, size_t count, loff_t *pos);实现步骤 检查用户缓冲区&#xff1a;使用copy_to_user将数据从内核空间复制到用户空间。返回已读取的字…...

腾讯微信C++面试题及参考答案

64 匹马 8 个赛道,找出前四名,最少赛多少场 为了找出64匹马中的前四名,我们可以按照以下步骤来组织比赛,尽量减少所需要的比赛次数: 初步分组: 将64匹马分成8组,每组8匹马。分别为A、B、C、D、E、F、G、H这8组。每组进行一次比赛来确定各组的速度排序。每个组比赛一次总…...

如何查看内网设备访问互联网时的出口 IP 地址?

在企业VPC中我们通常是一个机房公用一个公网IP&#xff0c;也就是所有的设备共用同一个出口IP。 那么如何查看如何查看内网设备访问互联网时的出口 IP 地址呢&#xff1f; 要查看一台 Linux 内网设备访问互联网时的出口 IP 地址&#xff0c;可以使用以下几种方法&#xff1a;…...

ESP32-S3模组上跑通ES8388(24)

接前一篇文章:ESP32-S3模组上跑通ES8388(23) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析完了es8388_init函数中的第8段代码,本回继续往下解析。为了便于理解和回顾,再次贴出es8388_init函数源码,在components\audio_hal\driver\es8388\es8388.c中,如下: ​ …...

【AIGC系列】frequency_penalty如何通过控制参数提升文本生成的多样性与创造性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Python+OpenCV系列:图像的运算

文章目录 PythonOpenCV系列&#xff1a;图像的加权和、覆盖1. 图像加权和&#xff08;加权融合&#xff09;2. 图像覆盖&#xff08;区域叠加&#xff09;3. 应用场景4. 总结 PythonOpenCV系列&#xff1a;图像的加权和、覆盖 在图像处理中&#xff0c;图像的加权和与覆盖是两…...

【Unity技巧】Unity项目中哪些文件不用管理(.gitignore)

Unity的项目编译后一般都比较大&#xff0c;动辙几个G。这里面一般我们只需要把Assets, Packages, ProjectSettings这三个文件夹进行源代码管理就可以&#xff0c;其他文件就可以通过下面的.gitignore来忽略掉。 .gitignore文件的内容如下&#xff1a; # 将此 .gitignore 文件…...

ansible 自动化运维工具(三)playbook剧本

目录 Playbook的定义 Playbook组成 Playbook命令 Playbook剧本编写格式 基本组件 Handlers处理器 tags标签 Facts组件 Register&#xff1a;注册变量 Debug模块 Playbook循环 With_items循环 With_dict循环&#xff08;字典循环&#xff09; With_nested循环&…...

图论【Lecode_HOT100】

文章目录 1.岛屿数量No.2002.腐烂的橘子No.9943.课程表No.2074.实现Trie&#xff08;前缀树&#xff09;No.208 1.岛屿数量No.200 class Solution {public int numIslands(char[][] grid) {if (grid null || grid.length 0) {return 0;}int numIslands 0;int rows grid.len…...

day10性能测试(2)——Jmeter

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、LoadRunner vs Jmeter 1.1 LoadRunner 1.2 Jmeter 1.3 对比小结 2、Jmeter 环境安装 2.1 安装jdk 2.2 安装Jmeter 2.3 小结 3、Jmeter 文件目录结构 4、Jmeter默认配置修改 5、Jmeter元件、组…...

Y3编辑器文档4:触发器

文章目录 一、触发器简介1.1 触发器界面1.2 ECA语句编辑及快捷键1.3 参数设置1.4 变量设置1.5 实体触发器1.6 函数库与触发器复用 二、触发器的多层结构2.1 子触发器&#xff08;在游戏内对新的事件进行注册&#xff09;2.2 触发器变量作用域2.3 复合条件2.4 循环2.5 计时器2.6…...

1. 机器学习基本知识(3)——机器学习的主要挑战

1.5 机器学习的主要挑战 1.5.1 训练数据不足 对于复杂问题而言&#xff0c;数据比算法更重要但中小型数据集仍然很普遍&#xff0c;获得额外的训练数据并不总是一件轻而易举或物美价廉的事情&#xff0c;所以暂时不要抛弃算法。 1.5.2 训练数据不具有代表性 采样偏差&#…...

prometheusgrafana实现监控告警

Prometheus负责集群数据的监控和采集&#xff0c;然后传递给grafana进行可视化&#xff0c;集成睿象云可实现监控报警&#xff0c;为了方便操作&#xff0c;可以通过iframe嵌套grafana到指定的页面。 文章目录 1.Grafana集成Prometheus2.iframe内嵌grafana3.监控告警 1.Grafana…...

Ubuntu防火墙管理(五)——ufw源规则解读与修改

firewalld与nftables 在 /etc/firewalld/firewalld.conf 文件中&#xff0c;FirewallBackend 选项用于指定 Firewalld 使用的防火墙后端实现。具体来说&#xff1a; nftables&#xff1a;这是当前的默认选项&#xff0c;表示 Firewalld 将使用 nftables 作为防火墙后端。nftab…...

Docker如何运行一个python脚本Hello World

Docker如何运行一个python脚本Hello World 1、编写Python的Hello World&#xff1a;script.py #!/usr/bin/python #_*_coding:utf-8_*_ print("Hello World") 2、Dockerfile文件 #拉取Docker环境 FROM python #设置工作目录 WORKDIR /app #将dockerfile同级文件copy到…...

人工智能-自动驾驶领域

目录 引言自动驾驶与人工智能的结合为什么自动驾驶领域适合发表文章博雅智信的自动驾驶辅导服务结语 引言 自动驾驶技术的崛起是当代交通行业的一场革命。通过结合先进的人工智能算法、传感器技术与计算机视觉&#xff0c;自动驾驶不仅推动了技术的进步&#xff0c;也使得未来…...

[ubuntu18.04]ubuntu18.04安装json-c操作说明

ubuntu18.04安装json-c 代码下载 rootw1804-virtual-machine:/home/w1804/tr069# git clone https://github.com/json-c/json-c.git Cloning into /opt/git/json-c... remote: Enumerating objects: 6398, done. remote: Counting objects: 100% (1067/1067), done. remote:…...

华为eNSP:VRRP

一、VRRP背景概述 在现代网络环境中&#xff0c;主机通常通过默认网关进行网络通信。当默认网关出现故障时&#xff0c;网络通信会中断&#xff0c;影响业务连续性和稳定性。为了提高网络的可靠性和冗余性&#xff0c;采用虚拟路由冗余协议&#xff08;VRRP&#xff09;是一种…...

Linux--top系统资源命令查看--详解

top命令用法 图&#xff1a; top命令用法&#xff1a; top命令经常用来监控linux的系统状况&#xff0c;是常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用情况。 top的使用方式&#xff1a; top [-d number] | top [-bnp] top参数解释&#xff1a; -…...

es的join是什么数据类型

在 Elasticsearch 中,parent 并不是一个独立的数据类型,而是与 join 数据类型一起使用的一个概念。join 数据类型用于在同一个索引中建立父子文档之间的关系,允许你在一个索引内表示层级结构或关联关系。通过 join 字段,你可以定义不同类型的文档(如父文档和子文档),并指…...

KV Shifting Attention Enhances Language Modeling

基本信息 &#x1f4dd; 原文链接: https://arxiv.org/abs/2411.19574&#x1f465; 作者: Mingyu Xu, Wei Cheng, Bingning Wang, Weipeng Chen&#x1f3f7;️ 关键词: KV shifting attention, induction heads, language modeling&#x1f4da; 分类: 机器学习, 自然语言处…...

软错误防护技术在车规MCU中应用

在大气层内&#xff0c;宇宙射线粒子与大气分子发生核反应生成大气中子。大气中子入射微电子器件或电路将会诱发单粒子效应&#xff08;SEE&#xff09;&#xff0c;效应类型主要有单粒子翻转&#xff08;SEU&#xff09;、单粒子瞬态&#xff08;SET&#xff09;、单粒子锁定&…...

遥感图像处理二(ENVI5.6 Classic)

1 实验目的和内容 1.1 实验目的 本次上机旨在继续深入了解ENVI软件的基本使用&#xff0c;并对提供的实验数据进行基本的图像分割和地物分类等操作并分析结果。 1.2 实验内容 1.2.1 图像分割 对教材示例数据“C7图像分割”中的风景图、兰花图和娃娃图分别进行图像分割操作…...

经典文献阅读之--A Fast Dynamic Point Detection...(用于驾驶场景中的动态点云剔除方法)

0. 简介 现有的基于3D点的动态点检测和移除方法存在显著的时间开销&#xff0c;使其难以适应激光雷达-惯性测程系统。《A Fast Dynamic Point Detection Method for LiDAR-Inertial Odometry in Driving Scenarios》提出了一种基于标签一致性的动态点检测和移除方法&#xff0…...

百度搜索应适用中文域名国家标准,修复中文网址展示BUG

12月1日中文域名国家标准正式实施。该标准“明确了中文域名在编码、解析、注册、字表等方面的技术要求&#xff0c;适用于中文域名注册管理机构、注册服务机构、网络软硬件服务商及终端用户”。 00:23 显然&#xff0c;百度作为网络软硬件服务商&#xff0c;是包括在国家标准的…...

设计模式学习之——适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;&#xff0c;又称作变压器模式&#xff08;因为这两者都体现了“转换”或“适配”的核心概念&#xff09;&#xff0c;是一种结构型设计模式。它将一个类的接口转换成客户端所期望的另一种接口&#xff0c;从而使得原本因接口…...

服务器数据恢复—热备盘上线过程中硬盘离线导致raid5阵列崩溃的数据恢复案例

服务器数据恢复环境&#xff1a; 两组分别由4块SAS接口硬盘组建的raid5阵列&#xff0c;两组raid5阵列划分LUN并由LVM管理&#xff0c;格式化为EXT3文件系统。 服务器故障&#xff1a; RAID5阵列中一块硬盘未知原因离线&#xff0c;热备盘自动激活上线替换离线硬盘。在热备盘上…...

MetaGPT源码 (Memory 类)

目录 MetaGPT源码&#xff1a;Memory 类例子 MetaGPT源码&#xff1a;Memory 类 这段代码定义了一个名为 Memory 的类&#xff0c;用于存储和管理消息(Message)对象。Memory 提供了多种操作消息的功能&#xff0c;包括添加单条或批量消息、按角色或内容筛选消息、删除最新消息…...

数据结构与算法复习AVL树插入过程

环境 $ cat /proc/version Linux version 6.8.0-45-generic (builddlcy02-amd64-115) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #45-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 30 12:02:04 UTC 2024 #include <std…...

小迪笔记第 五十天 文件包含漏洞 远程包含 本地包含 ctf练习题实战

前言 文件包含漏洞 原理就是包含的文件如果可控就会造成这个漏洞 php文件包含的特征 &#xff1a; PHP&#xff1a;include、require、include_once、require_once等 一共是分为了2 种 一个就是 远程文件包含 这个的前提是php开启了 远程文件上传这个选项 原理应用就是…...

制作个人免费网站展示设计/武汉网优化seo公司

首先 下载并安装好网易MuMu模拟器: https://mumu.163.com/mac/index.html 运行网易MuMu,打开后在首页打开设置->开发者选项->打开USB调试模式 如果已经打包好的apk文件&#xff0c;则直接将apk文件拖动到模拟器窗口&#xff0c;apk会被自动安装 ADB connect 这里需要说明…...

wordpress和avada/广告投放代理商加盟

一&#xff1a;empty()&#xff1b;判断一个变量是否被认为是空的。当一个变量并不存在&#xff0c;或者它的值等同于FALSE&#xff0c;那么它会被认为不存在。如果变量不存在的话&#xff0c;empty()并不会产生警告。 返回值 当var存在&#xff0c;并且是一个非空非零的值时…...

做盗文网站/搜外网友情链接

在长久的“裸奔”之后&#xff0c;电动平衡车即将穿上“衣服”。 早先&#xff0c;北京、上海等地已经陆续出台了相关政策&#xff0c;全面禁止电动平衡车、电动滑板等违规交通工具上路。而在近日&#xff0c;首个电动平衡车标准也新鲜出炉了。 昨天&#xff0c;在国家质检总局…...

免费创办网站/html网页制作app

大小&#xff1a;55.24MB语言&#xff1a;简体分类&#xff1a; 网页辅助版本&#xff1a; 电脑版立即下载 查看详情本文将给大家介绍如何使用八爪鱼采集器采集分页列表页面上的信息&#xff0c;并附带给大家讲一下ajax延时设置。目的是让大家了解怎么创建循环翻页并能正常采集…...

个人网站的作用/济南网站建设哪家好

房地产是支柱产业占GDP的比重很高 房地产是民生产业&#xff0c;老百姓的财富&#xff0c;60%在房地产&#xff0c;也该稳定&#xff1b; 房地产是半金融产业&#xff0c;大量的按揭贷款&#xff0c;它崩盘的话&#xff0c;对金融机构也是问题&#xff1b; 房地产还和大量的供应…...

深圳网站建设怎样容易/网络营销软文范例500字

这次需要记录一下我搭建web服务器的过程。 第一步&#xff0c;确定自己要使用的平台&#xff1a;这次我用的是windows2008 server版本 第二步&#xff0c;计划是想要纯手工的安装apache、php等。但是我们可以下载一个wamp集成版&#xff08;即windows系统下apache、mysql 、php…...