linux 驱动——私有数据

文章目录

  • linux 驱动中的私有数据
    • container_of
    • 驱动程序
    • 应用程序
    • 模块使用

linux 驱动中的私有数据

container_of

参考:linux——宏 list_entry/container_of

驱动程序

#include "linux/device/class.h"
#include "linux/export.h"
#include "linux/uaccess.h"
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>#define CHRDEVBASE_NAME "chrdevbase" /* 设备名 */
#define CHRDEVBASE_NUM 2             /* 设备数目 */static char *string_test = "kernel data this tyustli test";typedef struct {dev_t dev_id;          /* 设备号 */struct cdev c_dev;     /* cdev */struct class *class;   /* 类 */struct device *device; /* 设备 */int major;             /* 主设备号 */int minor;             /* 次设备号 */char write_buf[100];char read_buf[100];
} new_chrdev_t;static new_chrdev_t new_chrdev1;
static new_chrdev_t new_chrdev2;static int chrdevbase_open(struct inode *inode, struct file *file)
{new_chrdev1.minor = 0;new_chrdev2.minor = 1;file->private_data =container_of(inode->i_cdev, new_chrdev_t, c_dev); /* 设置私有数据 */printk("k: chrdevbase open\r\n");return 0;
}static ssize_t chrdevbase_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret = 0;new_chrdev_t *dev = (new_chrdev_t *)file->private_data;printk("k: chrdevbase read major %d\r\n", dev->major);memcpy(dev->read_buf, string_test, strlen(string_test));ret = copy_to_user(buf, dev->read_buf, count);if (ret == 0) {printk("k: read data success\r\n");} else {printk("k: read data failed ret = %ld\r\n", ret);}return ret;
}static ssize_t chrdevbase_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{unsigned long ret = 0;printk("k: chrdevbase write\r\n");new_chrdev_t *dev = (new_chrdev_t *)file->private_data;printk("k: chrdevbase read minor %d\r\n", dev->minor);ret = copy_from_user(dev->write_buf, buf, count);if (ret == 0) {printk("k: write data success write data is: %s\r\n", dev->write_buf);} else {printk("k: write data failed ret = %ld\r\n", ret);}return count;
}static int chrdevbase_release(struct inode *inode, struct file *file)
{printk("k: chrdevbase release\r\n");return 0;
}static struct file_operations chrdevbase_fops = {.owner = THIS_MODULE,.open = chrdevbase_open,.read = chrdevbase_read,.write = chrdevbase_write,.release = chrdevbase_release,
};static int __init chrdevbase_init(void)
{int err = 0;err = alloc_chrdev_region(&new_chrdev1.dev_id, 0, CHRDEVBASE_NUM,CHRDEVBASE_NAME);if (err < 0) {printk("k: alloc chrdev region failed err = %d\r\n", err);goto err_chrdev;}/* get major 1 and minor 1 */new_chrdev1.major = MAJOR(new_chrdev1.dev_id);new_chrdev1.minor = MINOR(new_chrdev1.dev_id);printk("k: newcheled major=%d,minor=%d\r\n", new_chrdev1.major,new_chrdev1.minor);new_chrdev1.c_dev.owner = THIS_MODULE;cdev_init(&new_chrdev1.c_dev, &chrdevbase_fops);err = cdev_add(&new_chrdev1.c_dev, new_chrdev1.dev_id, 1);if (err < 0) {printk("k: cdev add failed err = %d\r\n", err);goto err_cdev_add;}new_chrdev1.class = class_create("chr_test1");if (IS_ERR(new_chrdev1.class)) {err = PTR_ERR(new_chrdev1.class);goto err_class_create;}new_chrdev1.device = device_create(new_chrdev1.class, NULL,new_chrdev1.dev_id, NULL, "chr_test1");if (IS_ERR(new_chrdev1.device)) {err = PTR_ERR(new_chrdev1.device);goto err_device_create;}/* get major 2 and minor 2 */new_chrdev2.dev_id = new_chrdev1.dev_id;new_chrdev2.major = MAJOR(new_chrdev2.dev_id);new_chrdev2.minor = MINOR(new_chrdev2.dev_id) + 1;printk("k: newcheled major=%d,minor=%d\r\n", new_chrdev2.major,new_chrdev2.minor);new_chrdev2.c_dev.owner = THIS_MODULE;cdev_init(&new_chrdev2.c_dev, &chrdevbase_fops);err = cdev_add(&new_chrdev2.c_dev, new_chrdev2.dev_id + 1, 1);if (err < 0) {printk("k: cdev add failed err = %d\r\n", err);goto err_cdev_add;}new_chrdev2.class = class_create("chr_test2");if (IS_ERR(new_chrdev2.class)) {err = PTR_ERR(new_chrdev2.class);goto err_class_create;}new_chrdev2.device = device_create(new_chrdev2.class, NULL, new_chrdev2.dev_id + 1, NULL, "chr_test2");if (IS_ERR(new_chrdev2.device)) {err = PTR_ERR(new_chrdev2.device);goto err_device_create;}printk("k: base module init\r\n");return 0;err_device_create:class_destroy(new_chrdev1.class);class_destroy(new_chrdev2.class);
err_class_create:cdev_del(&new_chrdev1.c_dev);cdev_del(&new_chrdev2.c_dev);
err_cdev_add:unregister_chrdev_region(new_chrdev1.dev_id, CHRDEVBASE_NUM);
err_chrdev:return err;
}static void __exit chrdevbase_exit(void)
{device_destroy(new_chrdev1.class, new_chrdev1.dev_id);device_destroy(new_chrdev2.class, new_chrdev2.dev_id);class_destroy(new_chrdev1.class);class_destroy(new_chrdev2.class);cdev_del(&new_chrdev1.c_dev);cdev_del(&new_chrdev2.c_dev);unregister_chrdev_region(new_chrdev1.dev_id, CHRDEVBASE_NUM);printk("k: base module exit!\r\n");
}module_init(chrdevbase_init);
module_exit(chrdevbase_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("tyustli");
MODULE_INFO(intree, "Y"); /* loading out-of-tree module taints kernel */

应用程序

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"static char usrdata[] = { "user data!" };int main(int argc, char *argv[])
{int fd, retvalue;char *filename;char readbuf[100], writebuf[100];if (argc != 3) {printf("u: error Usage!\r\n");return -1;}filename = argv[1];/* 打开驱动文件 */fd = open(filename, O_RDWR);if (fd < 0) {printf("u: can't open file %s\r\n", filename);return -1;}/* 从驱动文件读取数据 */if (atoi(argv[2]) == 1) {retvalue = read(fd, readbuf, 50);if (retvalue < 0) {printf("u: read file %s failed!\r\n", filename);} else {/*  读取成功,打印出读取成功的数据 */printf("u: read data:%s\r\n", readbuf);}}/* 向设备驱动写数据 */if (atoi(argv[2]) == 2) {memcpy(writebuf, usrdata, sizeof(usrdata));retvalue = write(fd, writebuf, 50);if (retvalue < 0) {printf("u: write file %s failed!\r\n", filename);}}/* 关闭设备 */retvalue = close(fd);if (retvalue < 0) {printf("u: can't close file %s\r\n", filename);return -1;}return 0;
}

模块使用

查看设备节点

ls /dev/

在这里插入图片描述

模块安装

modprobe my_module

模块使用

#设备1
lib/modules/6.5.7+/my_app /dev/chr_test1  1
lib/modules/6.5.7+/my_app /dev/chr_test1  2
#设备2
lib/modules/6.5.7+/my_app /dev/chr_test2  1
lib/modules/6.5.7+/my_app /dev/chr_test2  2

模块打印日志

~ # lib/modules/6.5.7+/my_app /dev/chr_test1  1
k: chrdevbase open
k: chrdevbase read major 248
k: read data success
u: read data:kernel data this tyustli test
k: chrdevbase release
~ # lib/modules/6.5.7+/my_app /dev/chr_test1  2
k: chrdevbase open
k: chrdevbase write
k: chrdevbase read minor 0
k: write data success write data is: user data!
k: chrdevbase release
~ # lib/modules/6.5.7+/my_app /dev/chr_test2  1
k: chrdevbase open
k: chrdevbase read major 248
k: read data success
u: read data:kernel data this tyustli test
k: chrdevbase release
~ # lib/modules/6.5.7+/my_app /dev/chr_test2 2
k: chrdevbase open
k: chrdevbase write
k: chrdevbase read minor 1
k: write data success write data is: user data!
k: chrdevbase release
~ # 

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

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

相关文章

Python人脸识别

实现效果 代码 import cv2# 加载人脸识别分类器 face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml)# 打开摄像头 cap cv2.VideoCapture(0)while True:# 读取摄像头捕获的帧ret, frame cap.read()# 将帧转换为灰度图像gray cv2.cvtColor(frame, c…

迪文屏开发保姆级教程——页面键盘

迪文屏页面键盘保姆级教程。 本篇文章主要介绍了在DGBUS平台上使用页面键盘的步骤。 迪文屏官方开发指南PDF&#xff1a;&#xff08;不方便下载的私聊我发给你&#xff09; https://download.csdn.net/download/qq_21370051/88647174?spm1001.2014.3001.5503https://downloa…

vivado 关于时钟

关于时钟 在数字设计中&#xff0c;时钟代表了从寄存器可靠传输数据的时间基准注册。AMD Vivado™集成设计环境&#xff08;IDE&#xff09;计时引擎使用时钟计算时序路径要求并通过以下方式报告设计时序裕度的特性松弛计算的方法有关更多信息&#xff0c;请参阅Vivado Design…

AI百模大战:引领行业变革与开启人才黄金时代

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux学习 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 技术进步&#xff1a;AI的飞速发展 1. 深度学习的多领域应用 2. 自然语言处理的语境理解提升 3. 计算机视觉的实时处理能力提高 4…

Python学习笔记(六):函数的多返回值、函数的多种参数使用形式、匿名函数、文件的读取操作、文件的写入 、文件的追加

目录 一、函数的多返回值 二、函数的多种参数使用形式 2.1位置参数 2.2关键字参数 2.3缺省参数 2.4不定长参数 三、匿名函数 3.1 函数作为参数传递 3.2 函数的定义 3.3 匿名函数定义语法&#xff1a; 四、文件的读取操作 4.1 open&#xff08;&#xff09;打开函数…

图卷积神经网络发展

1. 图神经网络&#xff08;GNN&#xff09; 图神经网络的概念最早在2005年提出。2009年Franco博士在其论文 [2]中定义了图神经网络的理论基础。 本文中所提到的图均指图论中的图(Graph)。它是一种由若干个结点(Node)及连接两个结点的边(Edge)所构成的图形&#xff0c;用于刻画…

【模式识别】解锁降维奥秘:深度剖析PCA人脸识别技术

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《模式之谜 | 数据奇迹解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1f30c;1 初识模式识…

智能化物联网(IoT):发展、问题与未来前景

导言 智能化物联网&#xff08;IoT&#xff09;作为信息技术领域的一项核心技术&#xff0c;正在深刻改变人们的生活和工作方式。本文将深入研究IoT的发展过程、遇到的问题及解决过程、未来的可用范围&#xff0c;以及在各国的应用和未来的研究趋势。探讨在哪些方面能够取得胜利…

k8s-ingress特性 9

TLS加密 创建证书 测试访问 auth认证 创建认证文件 rewrite重定向 进入域名时&#xff0c;会自动重定向到hostname.html 示例&#xff1a; 测试 版本的升级迭代&#xff0c;之前利用控制器进行滚动更新&#xff0c;在升级过程中无法做到快速回滚 更加平滑的升级&#xff1…

【数据结构】线段树算法总结(区间修改)

知识概览 线段树一般有5个操作&#xff1a; pushup&#xff1a;用子节点更新当前节点信息pushdown&#xff1a;把懒标记往下传build&#xff1a;初始化一棵树modify&#xff1a;修改一个区间query&#xff1a;查询一个区间 不带懒标记&#xff08;支持单点修改&#xff09;的线…

Mysql-干净卸载教程

卸载 服务停掉 先把mysql服务停掉&#xff0c;如下点击右键&#xff0c;停止运行。 删除C盘内文件 接下来c盘里面的三个文件下的MySQL一一删除&#xff0c;需要注意的是 需要注意的是programdata文件下可能 隐藏了MySQL文件&#xff0c;所以可以在查看选项显示隐藏的文件。 …

PolarDB-X、OceanBase、CockroachDB、TiDB二级索引写入性能测评

为什么要做这个测试 二级索引是关系型数据库相较于NoSQL数据库的一个关键差异。二级索引必须是强一致的&#xff0c;因此索引的写入需要与主键的写入放在一个事务当中&#xff0c;事务的性能是二级索引性能的基础。 目前市面上的分布式数据库中&#xff0c;从使用体验的角度看…

前后端分离下的鸿鹄电子招投标系统:使用Spring Boot、Mybatis、Redis和Layui实现源码与立项流程

在数字化时代&#xff0c;采购管理也正经历着前所未有的变革。全过程数字化采购管理成为了企业追求高效、透明和规范的关键。该系统通过Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;打造了从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通过…

argmin与argmax

argmin 是一个数学术语&#xff0c;用于表示一个函数在其定义域中取得最小值的参数值&#xff08;自变量的值&#xff09;&#xff0c;而不是最小值本身。 具体来说&#xff0c;argmin 表示函数的自变量&#xff08;通常是一个实数或向量&#xff09;&#xff0c;当输入到该函数…

JavaWeb笔记之前端开发JavaScript

一、引言 1.1 简介 JavaScript一种解释性脚本语言&#xff0c;是一种动态类型、弱类型、基于原型继承的语言&#xff0c;内置支持类型。 它的解释器被称为JavaScript引擎&#xff0c;作为浏览器的一部分&#xff0c;广泛用于客户端的脚本语言&#xff0c;用来给HTML网页增加…

统计个数并调用--函数设计与实现

#定义函数 count(s) ,统计字符串中小写字母、大写字母、数字的个数&#xff0c;并以字典为结果返回给调用函数。 # (1)判断字符类型 def count(s):#创建字典&#xff0c;用于保存变量dictionary {数字: 0, 小写字母: 0, 大写字母: 0, 其他字符: 0}for c in s:if c.isdigit():d…

React学习计划-React16--React基础(三)收集表单数据、高阶函数柯里化、类的复习

1. 收集表单数据 包含表单的组件分类 受控组件——页面中所有输入类的DOM,随着输入&#xff0c;把值存维护在状态里&#xff0c;需要用的时候去状态里取值&#xff08;推荐&#xff0c;避免了过渡使用ref&#xff09;非受控组件——页面中所有输入类的DOM&#xff0c;现用现取…

Java 并发编程 —— Fork/Join 框架的原理详解

目录 一. 前言 二. 并发和并行 2.1. 并发 2.2. 并行 2.3. 分治法 三. ForkJoin 并行处理框架的理论 3.1. ForkJoin 框架概述 3.2. ForkJoin 框架原理 3.3. 工作窃取算法 四. ForkJoin 并行处理框架的实现 4.1. ForkJoinPool 类 4.2. ForkJoinWorkerThread 类 4.3.…

MongoDB的原子操作findAndModify和findOneAndUpdate

本文主要介绍MongoDB的原子操作findAndModify和findOneAndUpdate。 目录 MongoDB的原子操作一、findAndModify二、findOneAndUpdate MongoDB的原子操作 MongoDB的原子操作指的是在单个操作中对数据库的数据进行读取和修改&#xff0c;并确保操作是原子的&#xff0c;即要么完全…

Swagger2之SpringBoot集成使用

前言&#xff1a; 我们对于Mybatis-Plus的分享较多&#xff0c;都是接触的一些数据库相关的知识&#xff0c;今天给大家带来的是Swagger2 Swagger2 1.介绍&#xff1a; Swagger2是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化Restful风格的web服务&#xff…