字符设备驱动读写操作实现

news2024/11/20 0:32:39

一、读操作实现

ssize_t xxx_read(struct file *filp, char __user *pbuf, size_t count, loff_t *ppos);
完成功能:读取设备产生的数据
参数:
    filp:指向open产生的struct file类型的对象,表示本次read对应的那次open
    pbuf:指向用户空间一块内存,用来保存读到的数据
    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对应的那次open
    pbuf:指向用户空间一块内存,用来保存被写的数据
    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 100

int major = 11;					//主设备号
int minor = 0;					//次设备号
int char_num = 1;				//设备号数量

struct cdev mydev;

char mydev_buf[BUF_LEN];
int curlen = 0;

int mychar_open (struct inode *pnode, struct file *pfile)//打开设备
{
	printk("open\n");
	return 0;
}

int mychar_close(struct inode *pnode, struct file *pfile)//关闭设备
{
	printk("close\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,
	.read = mychar_read,
	.write = mychar_write,
	.release = mychar_close,
};

int __init mychar_init(void) 
{
	int ret = 0;
	dev_t devno = MKDEV(major, minor);

	/* 手动申请设备号 */
	ret = register_chrdev_region(devno, char_num, "mychar");
	if (ret) {
		/* 动态申请设备号 */
		ret = alloc_chrdev_region(&devno, minor, char_num, "mychar");
		if(ret){
			printk("get devno failed\n");
			return -1;
		}
		/*申请成功 更新设备号*/
		major = MAJOR(devno);
	}
	
	cdev_init(&mydev, &myops);

	mydev.owner = THIS_MODULE;
	cdev_add(&mydev, devno, char_num);

	return 0;
}

void __exit mychar_exit(void) 
{

	dev_t devno = MKDEV(major, minor);
	printk("exit %d\n", devno);
	
	/* 从内核中移除一个字符设备 */
	cdev_del(&mydev);

	/* 回收设备号 */
	unregister_chrdev_region(devno, char_num);

}

MODULE_LICENSE("GPL");
module_init(mychar_init);
module_exit(mychar_exit);

testmychar_app.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
{
	int fd = -1;
	char buf[32] = "";

	if(argc < 2) {
		printf("The argument is too few\n");
		return -1;
	}

	fd = open(argv[1], O_RDWR);
	if(fd < 0) {
		perror("open");
		return -1;
	}

	write(fd, "hello", 6);

	read(fd, buf, 32);

	printf("buf = %s\n", buf);
	close(fd);
	fd = -1;
	return 0;
}

Makefile

ifeq ($(KERNELRELEASE),)

ifeq ($(ARCH),arm)
KERNELDIR ?= /home/myubuntu/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) modules

modules_install:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install

clean:
	rm -rf  *.o  *.ko  .*.cmd  *.mod.*  modules.order  Module.symvers   .tmp_versions

else
# obj-m += myhello.o

# obj-m += mytest.o
# mytest-objs = test.o func.o

# obj-m += testparam.o

obj-m += mychar.o
endif

实现结果:
在这里插入图片描述

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

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

相关文章

十四五双碳双控时代下的“低碳认证”

目录 前言 十四五双碳双控时代下的“低碳认证” 一、关于“低碳认证” 二、低碳认证优势 三、环境产品认证EPD 四、EPD相关运营机构 五、碳中和相关机构 六、EPD的认证流程 七、低碳产品认证认证流程和要求 八、相关机构认证证书样例 九、证书附件表 前言 通过本篇文…

JavaWeb JQuery操作结点

目录 一、查找结点 1.简介 : 2.实例 : 二、创建结点 1.创建结点介绍 : 2.内部插入 : 2.1 介绍 : 2.2 实例 3.外部插入 : 3.1 介绍 3.2 实例 三、结点的其他相关操作 1.删除结点 &#xff1a; 2.复制结点 : 3.替换结点 : 4.遍历结点 : 一、查找结点 1.简介 : 查找到…

RAID磁盘阵列(RAID0/1/4/6/1+0)

目录 一、概述&#xff1a; 二、RAID 级别介绍 RAID 0 RAID 1 RAID 4 RAID 5 RAID 6 RAID10&#xff1a; 一、概述&#xff1a; RAID&#xff08; Redundant Array of Inexpensive Disks&#xff09;称为廉价磁盘冗余阵列。 RAID 的基本思想是把多个便宜的小磁盘组合到…

编写简单的支付接口测试用例思路

支付接口Python代码示例 以下是一个简单的支付接口Python代码示例&#xff0c;实现了用户登录后购买商品并支付的功能&#xff1a; import requests import json # 定义支付接口的URL和请求参数 url "https://example.com/pay" payment_data {"username&quo…

【业务功能篇87】微服务-springcloud-本地缓存-redis-分布式缓存-缓存穿透-雪崩-击穿

一、缓存 1. 什么是缓存 缓存的作用是减低对数据源的访问频率。从而提高我们系统的性能。 缓存的流程图 2.缓存的分类 2.1 本地缓存 其实就是把缓存数据存储在内存中(Map <String,Object>).在单体架构中肯定没有问题。 单体架构下的缓存处理 2.2 分布式缓存 在分布式环…

Iterator: hasNext()、next()、remove()

一、Iterator的API 关于Iterator主要有三个方法&#xff1a;hasNext()、next()、remove() hasNext:没有指针下移操作&#xff0c;只是判断是否存在下一个元素next&#xff1a;指针下移&#xff0c;返回该指针所指向的元素remove&#xff1a;删除当前指针所指向的元素&#xf…

树莓派 SSD1306

树莓派安装python3.9以及pip换源_树莓派安装pip_&#xff2c;&#xff2a;&#xff38;的博客-CSDN博客 树莓派使用 Python 驱动 SSD1306&#xff08;IIC/SPI 通信&#xff09; 进阶篇——树莓派OLED模块的使用 大量例程详解_oled例程_玩转智能机器人的博客-CSDN博客 使用OS 版…

从零开始学习盲盒小程序开发

在当前的电商市场中&#xff0c;微信盲盒小程序以其独特的互动性和惊喜感&#xff0c;已经成为吸引消费者的一种新兴电商模式。如果你也想搭建自己的微信盲盒小程序&#xff0c;本文将详细介绍如何从零开始实现这一目标。 第一步&#xff1a;登录【乔拓云】网后台&#xff0c;进…

自然语言处理2-NLP

目录 自然语言处理2-NLP 如何把词转换为向量 如何让向量具有语义信息 在CBOW中 在Skip-gram中 skip-gram比CBOW效果更好 CBOW和Skip-gram的算法实现 Skip-gram的理想实现 Skip-gram的实际实现 自然语言处理2-NLP 在自然语言处理任务中&#xff0c;词向量&#xff08;…

利用fsimage分析HDFS小文件

一、Hive 小文件概述 在Hive中&#xff0c;所谓的小文件是指文件大小远小于HDFS块大小的文件&#xff0c;通常小于128 MB&#xff0c;甚至更少。这些小文件可能是Hive表的一部分&#xff0c;每个小文件都包含一个或几个表的记录&#xff0c;它们以文本格式存储。 Hive通常用于…

卫星网络中的量子通信

当今社会&#xff0c;通信已经成为人类生活中不可或缺的一部分&#xff0c;而随着科技的迅猛发展&#xff0c;我们的通信方式也在不断革新和进化。近年来&#xff0c;量子通信作为一项引人瞩目的领域&#xff0c;正逐渐走入人们的视野。与传统通信方式相比&#xff0c;量子通信…

渗透测试漏洞原理之---【任意文件上传漏洞】

文章目录 1、任意文件上传概述1.1、漏洞成因1.2、漏洞危害 2、WebShell解析2.1、Shell2.2、WebShell2.2.1、大马2.2.2、小马2.2.3、GetShell 3、任意文件上传攻防3.1、毫无检测3.1.1、源代码3.1.2、代码审计3.1.3、靶场试炼 3.2、黑白名单策略3.2.1、文件检测3.2.2、后缀名黑名…

【AI】数学基础——线代(矩阵特征值,特征向量矩阵分解)

【AI】数学基础——线代&#xff08;向量部分&#xff09; 文章目录 2.3 矩阵2.3.1 二元方程组求解与行列式行列式 2.3.2 用矩阵形式表示数据矩阵与行列式区别特殊矩阵 2.3.3 矩阵的秩矩阵的秩 2.3.4 矩阵运算加减法数乘运算矩阵乘向量线性变换角度线性组合角度 矩阵乘矩阵转置…

MySQL有哪些常见的存储引擎?

主要存储引擎 主要的三个存储引擎MyISAMMemoryInnoDB 那存储引擎应该怎么选择&#xff1f;InnoDB 和 MylSAM 主要有什么区别&#xff1f; MySQL有9种存储引擎&#xff0c;不同的引擎&#xff0c;适合不同的场景&#xff0c;我们最常用的&#xff0c;可能就是InnoDB&#xff0c;…

向前兼容与向后兼容

2012年3月发布了Go 1.0,随着 Go 第一个版本发布的还有一份兼容性说明文档。该文档说明&#xff0c;Go 的未来版本会确保向后兼容性&#xff0c;不会破坏现有程序。 即用10年前Go 1.0写的代码&#xff0c;用10年后的Go 1.18版本&#xff0c;依然可以正常运行。即较高版本的程序能…

泰凌微科创板成功上市

2023年8月25日&#xff0c;泰凌微电子&#xff08;上海&#xff09;股份有限公司&#xff08;股票简称“泰凌微”&#xff0c;股票代码为“688591.SH”&#xff09;成功于上海证券交易所科创板挂牌上市。自泰凌微成立以来&#xff0c;便一直致力于研发具有自主知识产权、国际一…

Matter 设备配网流程 ---- 配网材料和 SPAKE2P 机制

Matter 设备配网流程 ---- 配网材料和 SPAKE2P 机制 1. Matter 配网材料 Matter 配网&#xff08;commissioning&#xff09;使用 SPAKE2P 协议完成 PASE&#xff0c;进而验证 DAC&#xff08;Device Attestation Credentials&#xff09;&#xff0c;派发 NOC&#xff0c;然…

ubuntu入门01——windows上直接部署linux(WSL)

win10安装参考如下教程&#xff1a; 旧版 WSL 的手动安装步骤 | Microsoft Learn 说明&#xff1a;该文档是我按如上教程安装使用Ubuntu写的回顾&#xff0c;家人们参考官方教程更妙。 1.启用适用于Linux的wundows子系统 2.启用虚拟机功能 dism.exe /online /enable-feat…

Java IO操作——BufferedReader

BufferReader Java IO操作——BufferedReader(缓冲区读取内容&#xff0c;避免中文乱码) 要点&#xff1a; 掌握BufferedReader类的使用 掌握键盘输入的基本形式 Buffer&#xff1a;表示缓冲区的。之前的StringBuffer&#xff0c;缓冲区中的内容可以更改&#xff0c;可以提高…

递归算法学习——子集

目录 一&#xff0c;题目解析 二&#xff0c;例子 三&#xff0c;题目接口 四&#xff0c;解题思路以及代码 1.完全深度搜索 2.广度搜索加上深度优先搜索 五&#xff0c;相似题 1.题目 2.题目接口 3.解题代码 一&#xff0c;题目解析 给你一个整数数组 nums &#xff0c…