lv 14 字符设备读写操作实现 5

一、读操作实现

ssize_t xxx_read(struct file *filp, char __user *pbuf, size_t count, loff_t *ppos);
完成功能:读取设备产生的数据
参数:filp:指向open产生的struct file类型的对象,表示本次read对应的那次openpbuf:指向用户空间一块内存,用来保存读到的数据count:用户期望读取的字节数ppos:对于需要位置指示器控制的设备操作有用,用来指示读取的起始位置,读完后也需要变更位置指示器的指示位置返回值:本次成功读取的字节数,失败返回-1

put_user(x,ptr)

x:char、int类型的简单变量名

unsigned long copy_to_user (void __user * to, const void * from, unsigned long n)

成功为返回0,失败非0

二、写操作实现

ssize_t xxx_write (struct file *filp, const char __user *pbuf, size_t count, loff_t *ppos);  
完成功能:向设备写入数据
参数:filp:指向open产生的struct file类型的对象,表示本次write对应的那次openpbuf:指向用户空间一块内存,用来保存被写的数据count:用户期望写入的字节数ppos:对于需要位置指示器控制的设备操作有用,用来指示写入的起始位置,写完后也需要变更位置指示器的指示位置返回值:本次成功写入的字节数,失败返回-1
​

get_user(x,ptr)

x:char、int类型的简单变量名

unsigned long copy_from_user (void * to, const void __user * from, unsigned long n)

成功为返回0,失败非0

三、示例

mychar.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>#define BUF_LEN 100int major = 11;
int minor = 0;
int mychar_num = 1;struct cdev mydev;char mydev_buf[BUF_LEN];
int curlen = 0;int mychar_open(struct inode *pnode,struct file *pfile)
{printk("mychar_open is called\n");return 0;
}int mychar_close(struct inode *pnode,struct file *pfile)
{printk("mychar_close is called\n");return 0;
}ssize_t mychar_read(struct file *pfile, char __user *puser, size_t count, loff_t *p_pos)
{int size = 0;int ret = 0;if(count > curlen){size = curlen;}else{size = count;}ret = copy_to_user(puser,mydev_buf,size);if(ret){printk("copy_to_user failed\n");return -1;}memcpy(mydev_buf,mydev_buf + size,curlen - size);curlen = curlen - size;return size;
}ssize_t mychar_write(struct file *pfile,const char __user *puser,size_t count, loff_t *p_pos)
{int size = 0;int ret = 0;if(count > BUF_LEN-curlen){size = BUF_LEN - curlen;}else{size = count;}ret = copy_from_user(mydev_buf + curlen,puser,size);if(ret){printk("copy_from user failed\n");return -1;}curlen = curlen + size;return size;
}struct file_operations myops = {.owner = THIS_MODULE,.open = mychar_open,.release = mychar_close,.read = mychar_read,.write = mychar_write,
};int __init mychar_init(void)
{int ret = 0;dev_t devno = MKDEV(major,minor);/*申请设备号*/ret = register_chrdev_region(devno,mychar_num, "mychar");if(ret){ret = alloc_chrdev_region(&devno,minor,mychar_num,"mychar");if(ret){printk("get devno failed\n");return -1;}major = MAJOR(devno);//容易遗漏,注意}/*给struct cdev对象指定操作函数集*/cdev_init(&mydev,&myops);/*将struct cdev对象添加到内核对应的数据结构里*/mydev.owner = THIS_MODULE;cdev_add(&mydev,devno,mychar_num);return 0;
}void  __exit mychar_exit(void)
{dev_t devno = MKDEV(major,minor);cdev_del(&mydev);unregister_chrdev_region(devno,mychar_num);
}MODULE_LICENSE("GPL");module_init(mychar_init);
module_exit(mychar_exit);

"copy_to_user" 是一个在操作系统中常见的函数或操作,用于将内核空间中的数据复制到用户空间中。在Linux内核中,copy_to_user() 函数用于将内核缓冲区中的数据复制到用户空间的缓冲区中。它的原型如下:

unsigned long copy_to_user(void __user *dst, const void *src, unsigned long size);

其中,dst 是指向用户空间缓冲区的指针,src 是指向内核空间缓冲区的指针,size 是要复制的数据的字节数。该函数返回成功复制的字节数,如果出现错误则返回一个负数。

需要注意的是,由于我是一个AI机器人,无法直接执行代码或提供实际的编程环境。如果你有关于 copy_to_user() 函数的具体问题,可以提供更多的背景信息,我将尽力给予帮助。

testmychar_app.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#include <stdio.h>int main(int argc,char *argv[])
{int fd = -1;char buf[8] = "";if(argc < 2){printf("The argument is too few\n");return 1;}fd = open(argv[1],O_RDWR);if(fd < 0){printf("open %s failed\n",argv[1]);return 2;}write(fd,"hello",6);read(fd,buf,8);printf("buf=%s\n",buf);close(fd);fd = -1;return 0;
}

Makefile 

ifeq ($(KERNELRELEASE),)ifeq ($(ARCH),arm)
KERNELDIR ?= /home/linux/Linux_4412/kernel/linux-3.14
ROOTFS ?= /opt/4412/rootfs
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_installclean:rm -rf  *.o  *.ko  .*.cmd  *.mod.*  modules.order  Module.symvers   .tmp_versionselse
CONFIG_MODULE_SIG=n
obj-m += mychar.oendif

避开使用全局变量,使得函数更通用一些

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

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

相关文章

分布式(7)

目录 31.基于Zookeeper如何实现分布式锁&#xff1f; 32.什么是ACID&#xff1f; 33.什么是分布式的XA协议&#xff1f; 34.什么是2PC&#xff1f; 35.什么是3PC&#xff1f; 31.基于Zookeeper如何实现分布式锁&#xff1f; 顺序节点 创建一个用于发号的节点“/test/lock…

Underactuated Robotics - 欠驱动机器人学

系列文章目录 DRAKE - 基于模型的机器人设计与验证 由丰田研究所支持的 C / Python 工具箱。 前言 © Russ Tedrake, 2023 注&#xff1a;这是麻省理工学院一门课程的工作笔记。它们将在 2023 年春季学期中不断更新。讲座视频可在 YouTube 上观看。 您也可以从这里下载…

应用在游戏机触摸屏中的触摸感应芯片

触屏游戏机的屏幕是由液晶屏和触控层组成的。触控层分为电容式触屏和电阻式触屏两种。电容式触屏是将悬空电极和屏幕玻璃上的电极组成静电场,当人体接近屏幕时,就会改变静电场分布,从而实现触摸的位置探测。而电阻式触屏则是利用玻璃上的两层电极之间通电形成一个电阻值,当手指…

【python入门】day19:学生管理系统需求分析、系统设计、主函数设计

需求分析 应具备功能—— 添加学生及成绩信息&#xff1b; 将学生信息保存到文件中&#xff1b; 修改和删除学生信息&#xff1b; 查询学生信息&#xff1b; 根据学生成绩进行排序&#xff1b; 统计学生的总分 系统设计 1.录入学生信息模块 2.查找 3.删除 4.修改 5.成绩排名…

数据分析求职-简历准备

简历在整个求职过程中的重要性不言而喻&#xff0c;今天咱们来聊求职过程中简历准备的那些事儿~ 1. 简历究竟有啥用 求职的流程简单说就是&#xff1a;网申->笔试->面试->offer 其中网申环节&#xff0c;简历100%决定了你的通过与否&#xff0c;这个点大家都知道。…

react 6种方式编写样式

在React中&#xff0c;编写样式主要有以下几种方式&#xff1a; 内联样式&#xff1a;直接在React组件中使用style属性来定义样式。这种方式比较适合定义动态的样式&#xff0c;因为它允许你将JavaScript表达式作为样式的值。 外部样式表&#xff1a;通过创建外部的CSS文件&am…

计算机Java项目|Springboot+vue 学生心理咨询评估系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

数据结构入门到入土——ArrayList与顺序表

目录 一&#xff0c;线性表 二&#xff0c;顺序表 1.接口实现 三&#xff0c;ArrayList简介 四&#xff0c;ArrayList使用 1.ArrayList的构造 2.ArrayList常见操作 3.ArrayList的遍历 4.ArrayList的扩容机制 五&#xff0c;ArrayLisit的具体使用 杨辉三角 一&#x…

linux 使用log4cpp记录项目日志

为什么要用log4cpp记录项目日志 在通常情况下&#xff0c;Linux/UNIX 每个程序在开始运行的时刻&#xff0c;都会打开 3 个已经打开的 stream. 分别用来输入&#xff0c;输出&#xff0c;打印错误信息。通常他们会被连接到用户终端。这 3 个句柄的类型为指向 FILE 的指针。可以…

【保研记录】2023年(24届)SE上岸经历

先开个坑&#xff0c;慢慢填~ 个人信息 学校&#xff1a;某双非 专业&#xff1a;软件工程 第四轮学科评估&#xff1a;无&#xff08;对就是没有等级&#xff09; 排名&#xff1a;1/400 竞赛/荣誉&#xff1a;国奖x2&#xff0c;省三好&#xff0c;大英国二&#xff0c;…

视频剪辑方法:一键批量转码,视频转GIF教程详解

在数字媒体时代&#xff0c;视频剪辑已经成为一项必备技能。无论是专业人士还是普通用户&#xff0c;都要对视频进行剪辑、转码和制作。但是视频剪辑并不简单&#xff0c;要掌握一定的技巧和知识。下面一起来看云炫AI智剪简单易学的视频剪辑方法&#xff1a;一键批量转码和视频…

案例093:基于微信小程序的南宁周边乡村游设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【MATLAB】【数字信号处理】线性卷积和抽样定理

已知有限长序列&#xff1a;xk1,2,1,1,0,-3, hk[1,-1,1] , 计算离散卷积和ykxk*h(k) 。 程序如下&#xff1a; function [t,x] My_conv(x1,x2,t1,t2,dt) %文件名与函数名对应 %自写的卷积函数 x conv(x1,x2)*dt; t0 t1(1) t2(1); L length(x1) length(x2)-2; t t0:dt…

thinkphp6入门(14)-- 多关联模型查询

背景&#xff1a; 有3个数据表&#xff0c;一个User表&#xff0c;一个Cloth表&#xff0c;一个Shoe表。 Cloth表和Shoe表分别和User表通过user_id关联。 thinkphp 6中如何通过模型查询所有用户&#xff0c;其中包括每个用户的cloth和shoe。 多关联模型查询&#xff1a; 1.…

Flask笔记六之中间件操作

本文首发于公众号&#xff1a;Hunter后端 原文链接&#xff1a;Flask笔记六之中间件操作 与 Django 一样&#xff0c;Flask 也提供了中间件的使用&#xff0c;用于在处理请求之前和之后执行一些公共逻辑 本篇笔记的代码都已经提交到 github 上&#xff0c;可使用下面的操作获取…

Qt6学习笔记:对象树

使用QObject及其子类创建的对象是以对象树的形式来组织的。创建一个QObject对象时若设置一个父对象&#xff0c;它就会被添加到父对象的子对象列表里&#xff0c;一个父对象被删除时&#xff0c;其全部的子对象都会自动删除。QObject类的构造函数里有一个参数用于设置对象的父对…

CommonJS 和 ES6 Module:一场模块规范的对决(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【自学笔记】01Java基础-02java基础语法-02变量、对象与类

1 变量、对象、类 变量&#xff1a; 变量是在编程中用来存储数据的占位符&#xff0c;它具有名称和值。在程序执行过程中&#xff0c;变量的值可以改变。根据作用域和生命周期的不同&#xff0c;变量可分为全局变量、局部变量、类变量&#xff08;静态变量&#xff09;、实例变…

五、书写规则

目录 一、规则举例 三、在规则中使用通配符 四、文件搜寻 五、伪目标 六、多目标 七、静态模式 八、自动生成依赖性 规则包含两个部分&#xff0c;一个是依赖关系&#xff0c;一个是生成目标的方法。 在 Makefile 中&#xff0c;规则的顺序是很重要的&#xff0c;因为&a…

python 数据容器

数据容器概念 一个可以存储多个元素的python数据类型 python有的数据容器 list(列表) tuple(元组) str(字符串) set(集合) dct(字典) 列表 python的列表的数据类型可以是不同的 my_list ["1",123,True,[123,"3333",d,False]]for item in my_list:p…