Linux字符设备驱动中同类型多设备节点的创建---一个驱动程序支持多个同类型设备

文章目录

  • 前言
  • 1 代码解析
    • 1.1 驱动层
    • 1.2 应用层
  • 2 运行结果
  • 总结


前言

本期分享的内容相对比较简单,那就是同时注册多个同类型的字符设备驱动,那么这样我们就可以同时支持多个同类型的设备了!下面来带大家看一下:


1 代码解析

1.1 驱动层

//本驱动程序支持主设备号major = 11,次设备号为0,1,2的三个设备
表明驱动程序支持三个同类型的设备,在使用时需要创建真实的设备节点
mknod /dev/mydev0 c 11 0
mknod /dev/mydev1 c 11 1
mknod /dev/mydev2 c 11 2
编写一个驱动程序,可以分别驱动三个设备节点

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include "mychar.h"#define BUF_LEN 		100
#define MYCHAR_DEV_CNT 	3
int major = 11; 		//主设备号
int minor = 0; 			//次设备号
int mychar_num = MYCHAR_DEV_CNT; 	//设备数量struct mychar_dev
{struct cdev mydev; 			//每一类设备都有一个cdev结构体char mydev_buf[BUF_LEN];  	//内核空间int curlen; 				//有效数字从零开始
};//创建MYCHAR_DEV_CNT个设备结构体
struct mychar_dev gmydev_arr[MYCHAR_DEV_CNT];int mychar_open(struct inode *pnode, struct file *pfile)
{pfile->private_data = (void *)container_of(pnode->i_cdev, struct mychar_dev, mydev);printk("mychar open is called!!!\n");return 0;
}ssize_t mychar_read(struct file *pfile, char __user *pbuf, size_t count, loff_t *ppos)
{int size = 0;int ret = 0;struct mychar_dev *pmydev = (struct mychar_dev *)pfile->private_data;if (count > pmydev->curlen){size = pmydev->curlen;}else{size = count;}ret = copy_to_user(pbuf, pmydev->mydev_buf, size);if (ret){printk("copy_to_user failed!\n");return -1;}memcpy(pmydev->mydev_buf, pmydev->mydev_buf + size, pmydev->curlen - size);   //把在mydev_buf中剩下有效数据存放在以mydev_buf的首地址中pmydev->curlen -= size; 			//读走的字节要被减去return size;
}ssize_t mychar_write(struct file *pfile, const char __user *pbuf, size_t count, loff_t *ppos)
{int size = 0;int ret = 0;struct mychar_dev *pmydev = (struct mychar_dev *)pfile->private_data;if (count < BUF_LEN - pmydev->curlen){size = count;}else{size = BUF_LEN - pmydev->curlen;}ret = copy_from_user(pmydev->mydev_buf + pmydev->curlen, pbuf, size);if (ret){printk("copy_from_user failed!\n");return -1;}pmydev->curlen += size;return size;
}long mychar_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
{int __user *pret = (int *)arg;int maxlen = BUF_LEN;int ret = 0;struct mychar_dev *pmydev = (struct mychar_dev *)pfile->private_data;switch(cmd){case MYCHAR_IOCTL_GET_MAXLEN:ret = copy_to_user(pret, &maxlen, sizeof(int));if (ret){printk("fail to copy_to_user!\n");return -1;}break;case MYCHAR_IOCTL_GET_CURLEN:ret = copy_to_user(pret, &pmydev->curlen, sizeof(int));if (ret){printk("fail to copy_from_user!\n");return -1;}break;default:printk("the cmd is unknow!\n");return -1;}return 0;
}int mychar_close(struct inode *pnode, struct file *pfile)
{printk("mychar clsoe is called!!!\n");return 0;
}/* 对字符设备的操作函数 */
struct file_operations myops = {.owner = THIS_MODULE,.open = mychar_open,.write = mychar_write,.read = mychar_read,.unlocked_ioctl = mychar_ioctl,	.release = mychar_close,
};int __init mychar_init(void)
{int ret = 0;int i = 0;dev_t devno = MKDEV(major, minor); 										//组合设备号ret = register_chrdev_region(devno, mychar_num, "mychar"); 				//手动申请设备号if (ret) 																//返回值为0表示申请成功{ret = alloc_chrdev_region(&devno, 0, mychar_num, "mychar"); 	//申请失败则系统自动分配if (ret){printk("get devno failed!\n");return -1;}major = MAJOR(devno); 												//从系统分配的设备号中取出主设备号minor = MINOR(devno); 												//从系统分配的设备号中取出次设备号devno = MKDEV(major, minor); 										//组合设备号}for (i = 0;i < MYCHAR_DEV_CNT;++i){devno = MKDEV(major, minor + i); 										//组合设备号/* 使得设备具有myops中的函数操作方法 */cdev_init(&gmydev_arr[i].mydev, &myops);gmydev_arr[i].mydev.owner = THIS_MODULE;/* 将设备号为devno的这个设备(mydev)添加到内核(内核hash链表中) */cdev_add(&gmydev_arr[i].mydev, devno, 1);}printk("hello world!\n");return 0;
}void __exit mychar_exit(void)
{int i = 0;dev_t devno = MKDEV(major, minor); 						//组合设备号for (i = 0;i < MYCHAR_DEV_CNT;++i){/* 从内核中删除mydev这个设备 */cdev_del(&gmydev_arr[i].mydev);}unregister_chrdev_region(devno, mychar_num); 		//注销设备号printk("bye bye!!!\n");
}MODULE_LICENSE("GPL");
module_init(mychar_init);
module_exit(mychar_exit);

1.2 应用层

应用层的代码没有任何修改!

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "mychar.h"int main(int argc, const char *argv[])
{int fd = -1;char buf[6];int max = 0;int cur = 0;if (argc < 2){printf("the arguement is too few!\n");return -1;}fd = open(argv[1], O_RDWR);if(fd < 0){printf("fail to open %s\n", argv[1]);return -1;}ioctl(fd, MYCHAR_IOCTL_GET_MAXLEN, &max);printf("max = %d\n", max);write(fd, "hello", 6);printf("max = %d\n", max);ioctl(fd, MYCHAR_IOCTL_GET_CURLEN, &cur);printf("cur = %d\n", cur);read(fd, buf, 6);printf("buf = %s\n", buf);close(fd);fd = -1;return 0;
}

2 运行结果

在这里插入图片描述
每一个设备文件都支持这样的操作,因此运行后的结果是完全一致的!


总结

本期的分享相对来讲比较简单,就是需要将以前的设备修改为数组,那么在驱动程序的入口和出口函数中都需要进行着重修改,也就是循环创建和删除!
最后,各位小伙伴们如果有收获,可以点赞收藏哦,你们的认可是我创作的动力,一起加油!

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

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

相关文章

基于springboot+vue的精准扶贫管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

从Unity到Three.js(outline 模型描边功能)

指定模型高亮功能&#xff0c;附带设置背景颜色&#xff0c;获取随机数方法。 百度查看说是gltf格式的模型可以携带PBR材质信息&#xff0c;如果可以这样&#xff0c;那就完全可以在blender中配置好材质导出了&#xff0c;也就不需要像在unity中调整参数了。 import * as THRE…

Autosar 开篇

背景 AUTOSAR&#xff08;Automotive Open System Architecture&#xff09;是一个跨汽车行业的标准化软件架构&#xff0c;旨在促进汽车电子系统的开发和部署。下面是AUTOSAR发展的一些关键点&#xff1a; 起源和背景&#xff1a; AUTOSAR最初于2003年由汽车制造商宝马、戴姆…

使用GPT生成python图表

首先&#xff0c;生成一脚本&#xff0c;读取到所需的excel表格 import xlrddata xlrd.open_workbook(xxxx.xls) # 打开xls文件 table data.sheet_by_index(0) # 通过索引获取表格# 初始化奖项字典 awards_dict {"一等奖": 0,"二等奖": 0,"三等…

MCU多核异构通信原理

摘要&#xff1a; 本文结合瑞萨RZ/G2L 多核处理器&#xff0c;给大家讲述一下多核异构设计及通信的原理。 随着电子技术的不断发展&#xff0c;以及市场需求的日益增长&#xff0c;嵌入式系统不仅要求执行复杂的控制任务&#xff0c;还需要实时地采集和处理数据。 为了满足这…

HarmonyOS开发行业前景就业分析与实例解析

HarmonyOS的简介 鸿蒙系统&#xff08;HarmonyOS&#xff09;是华为公司自主研发的一种全场景分布式操作系统&#xff0c;旨在为各种设备提供统一的开发和运行环境。它的编程基础主要建立在多种技术和语言之上&#xff0c;包括鸿蒙系统的核心框架和应用程序开发框架。 本章将…

Easy-Jmeter: 性能测试平台

目录 写在开始1 系统架构2 表结构设计3 测试平台生命周期4 分布式压测5 压力机管理6 用例管理6.1 新增、编辑用例6.2 调试用例6.3 启动测试6.4 动态控量6.5 测试详情6.6 环节日志6.7 实时数据6.8 测试结果 7 测试记录7 用例分析8 系统部署8.1普通部署8.2容器化部署 写在最后 写…

【技术分享】使用nginx完成动静分离➕集成SpringSession➕集成sentinel➕集成seata

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于技术点的相关分享吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 一、 使用nginx完成动静分离 1.下载…

【数据集】世界水评估方案指标:灌溉面积/灌溉用水等

世界水评估方案指标 概述(Overview)数据下载(Data Download)案例1:F. Irrigated lands案例2:G. Irrigated water use参考World Water Development Report II-Indicators for World Water Assessment Programme 概述(Overview) 在关于全球环境变化和可持续发展的辩论…

微信小程序(1)- 小程序开发工具

1. 小程序开发工具下载 地址&#xff1a;官网 微信小程序账号只要开发者满足开发资质都可以进行注册&#xff0c;并且会获得对应的 开发者 ID。一个完整的开发者 ID 由 小程序 ID&#xff08;AppID&#xff09;和一个 小程序密钥&#xff08;AppSecret&#xff09;组成。小程…

JAVA算法和数据结构

一、Arrays类 1.1 Arrays基本使用 我们先认识一下Arrays是干什么用的&#xff0c;Arrays是操作数组的工具类&#xff0c;它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。 下面我们用代码来演示一下&#xff1a;遍历、拷贝、排序等操作。需要用到的方法如下 public…

嵌入式学习第二十天!(进程)

进程基本概念&#xff1a; 1. 进程&#xff1a; 程序&#xff1a;存放在外存中的一段数据组成的文件 进程&#xff1a;是一个程序动态执行的过程&#xff0c;包括进程的创建、进程的调度、进程的消亡 2. 进程相关命令&#xff1a; 1. top: 动态查看当前系统中的所有进程信息…

HarmonyOS—添加/删除Module

Module是应用/服务的基本功能单元&#xff0c;包含了源代码、资源文件、第三方库及应用/服务配置文件&#xff0c;每一个Module都可以独立进行编译和运行。一个HarmonyOS应用/服务通常会包含一个或多个Module&#xff0c;因此&#xff0c;可以在工程中创建多个Module&#xff0…

docker部署grafana+zabbix监控

1. grafana介绍 Grafana 是一个开源的数据可视化工具&#xff0c;它可以帮助用户将数据源中的数据进行图形化展示和实时监控&#xff0c;以便于用户能够更加直观地理解数据。Grafana 支持多种数据源&#xff0c;包括 Graphite、Elasticsearch、InfluxDB、Prometheus 等&#x…

SpringBoot -【BeanFactory】基础使用及应用场景

1.介绍 在 Spring 框架中&#xff0c;BeanFactory 是 Spring IoC 容器的核心接口&#xff0c;负责管理 bean 的创建、配置和装配。它是 Spring IoC 容器的基础。BeanFactory 接口定义了一系列方法&#xff0c;用于管理和访问容器中的 bean 对象。 BeanFactoryAware 用于在 Sp…

相机图像质量研究(39)常见问题总结:编解码对成像的影响--运动模糊

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

智慧医疗新篇章:山海鲸可视化引领行业变革

随着科技的不断发展&#xff0c;智慧医疗已经成为医疗行业的新趋势。山海鲸可视化以其独特的视角和前沿的技术&#xff0c;为智慧医疗提供了全方位的解决方案。其强大的数据可视化能力&#xff0c;使得医疗数据更加直观、易于理解。无论是病例分析、手术模拟&#xff0c;还是患…

【GB28181】wvp-GB28181-pro部署安装教程(Ubuntu平台)

目录 前言1 安装依赖2 安装MySQL3 安装redis4 编译ZLMediaKit代码及依赖下载编译运行&#xff08;如果要运行wvp整个项目&#xff0c;这步可以先不执行&#xff09; 5 编译wvp-pro下载源码&#xff08;建议从github上下载&#xff0c;gitee上维护有时候不是很同步&#xff09;编…

半导体物理基础-笔记(续)

源内容参考&#xff1a;https://www.bilibili.com/video/BV11U4y1k7zn/?spm_id_from333.337.search-card.all.click&vd_source61654d4a6e8d7941436149dd99026962 掺杂半导体的费米能级与温度及杂质浓度的关系图 在温度一定的条件下&#xff0c;施主杂质浓度越高&#xff0…

20210505-20240223 CSDN 1024天 创作纪念日

作为一个小白&#xff0c;我没想到自己在不知不觉间就走过了如此长久的一段旅程。恍然间&#xff0c;三年多的时光已经过去了。 机缘 我首次写博客是为了记录日常&#xff0c;分享生活。 在这1024天里&#xff0c;我做了一些记录和分享&#xff0c;特别是遇到一些有趣的、值得…