linux 驱动——私有数据

文章目录

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

linux 驱动中的私有数据

前面的程序中,都只申请了一个从设备号,这里使用 alloc_chrdev_region 分配两个设备号,这两个设备共用 ops 方法。

所以需要在 ops 方法中区分两个设备

container_of

参考:linux——宏 list_entry/container_of

驱动程序

数据结构定义

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;

这里定义了两个设备,分别为 new_chrdev1 和 ·new_chrdev2·

  • new_chrdev1
    • 设备号:通过 alloc_chrdev_region 分配;
    • 主设备号:major = MAJOR(dev_id);
    • 次设备号:minor = MINOR(dev_id);
  • new_chrdev2
    • 主设备号:major = MAJOR(new_chrdev1.dev_id);
    • 次设备号:minor = MINOR(new_chrdev1.dev_id) + 1;
    • 设备号: dev_id = MKDEV(new_chrdev2.major, new_chrdev2.minor);

程序源码

#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.major = MAJOR(new_chrdev2.dev_id);new_chrdev2.minor = MINOR(new_chrdev2.dev_id) + 1;new_chrdev2.dev_id = MKDEV(new_chrdev2.major, new_chrdev2.minor);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);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, 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;
}

模块使用

模块安装

modprobe my_module

查看设备节点

ls /dev/

在这里插入图片描述

模块使用

#设备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.hqwc.cn/news/292814.html

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

相关文章

福建农林大学 html +css + JavaScript 期末复习 -- 保姆级

html css JavaScript 期末复习&#xff08;保姆级复盘&#xff09; 考试题型 1、选择题 20题 30分 2、判断题 15题 15分 3、程序题 3 题 30分 4、综合题 2 题 25分 1、网页第一代文本标签&#xff08;直接上代码&#xff0c;看保姆级注解&#xff09; <!-- doctype: docum…

【Spring Boot】面试题汇总,带答案的那种

继上次的文章【MySQL连环炮&#xff0c;你抗的住嘛&#xff1f;】爆火之后&#xff0c;越来越多的小伙伴后台留言&#xff0c;要求阿Q总结下其他的“连环炮”知识点&#xff0c;想在金九银十的面试黄金期轻松对线面试官。 同样为了节省大家的时间&#xff0c;阿Q最近对【Sprin…

世界第一!移动云刷新虚拟化性能测试世界纪录

近日&#xff0c;国际权威性能测评机构SPEC公布了最新一期虚拟化性能基准测试结果&#xff0c;移动云大云天元操作系统&#xff08;BC-Linux&#xff09;&#xff0c;凭借其出色的虚拟化性能&#xff0c;一举将世界纪录提升了10%&#xff0c;总分达到了8336分。 移动云SPEC vir…

口碑好的国产主食冻干猫粮品牌有哪些?盘点十大放心猫粮国产名单

冻干猫粮可以帮助猫咪摄入更多的水分&#xff0c;因为冻干是高蛋白质的食物&#xff0c;当猫咪吃了冻干猫粮后&#xff0c;会感到口渴&#xff0c;从而更主动地去喝水。对于那些不喜欢喝水的猫咪&#xff0c;可以将冻干复水后再喂给它们&#xff0c;这样也可以增加猫咪的水分摄…

管理类联考——数学——真题篇——按题型分类——充分性判断题——蒙猜C

老规矩&#xff0c;先看目录&#xff0c;平均每个3-4C&#xff08;C是月饼&#xff0c;月饼一般分为4块&#xff09; C是什么&#xff0c;是两个都不行了&#xff0c;但联合起来可以&#xff0c;联合的英文是combined&#xff0c;好的&#xff0c;我知道这个英文也记不住&#…

深度学习目标检测(2)yolov3设计思想

YOLOv3基础 YOLOv3算法基本思想可以分成两部分&#xff1a; 按一定规则在图片上产生一系列的候选区域&#xff0c;然后根据这些候选区域与图片上物体真实框之间的位置关系对候选区域进行标注。跟真实框足够接近的那些候选区域会被标注为正样本&#xff0c;同时将真实框的位置…

RTP/RTCP/RTSP/SIP/SDP/RTMP对比

RTP&#xff08;Real-time Transport Protocol&#xff09;是一种用于实时传输音频和视频数据的协议。它位于传输层和应用层之间&#xff0c;主要负责对媒体数据进行分包、传输和定时。 RTCP&#xff08;Real-Time Control Protocol&#xff09;是 RTP 的控制协议&#xff0c;…

SSM整合实战(Spring、SpringMVC、MyBatis)

五、SSM整合实战 目录 一、SSM整合理解 1. 什么是SSM整合&#xff1f;2. SSM整合核心理解五连问&#xff01; 2.1 SSM整合涉及几个IoC容器&#xff1f;2.2 每个IoC容器盛放哪些组件&#xff1f;2.3 IoC容器之间是什么关系&#xff1f;2.4 需要几个配置文件和对应IoC容器关系&…

【C语言】自定义类型:结构体深入解析(二)结构体内存对齐宏offsetof计算偏移量结构体传参

文章目录 &#x1f4dd;前言&#x1f320; 结构体内存对齐&#x1f309;内存对齐包含结构体的计算&#x1f320;宏offsetof计算偏移量&#x1f309;为什么存在内存对⻬?&#x1f320; 结构体传参&#x1f6a9;总结 &#x1f4dd;前言 本小节&#xff0c;我们学习结构的内存对…

阳台局部改造,这4个步骤一个都不能少!福州中宅装饰,福州装修

亲爱的读者们&#xff0c;你们是否曾经梦想过对自己的阳台进行一次彻底的改造&#xff0c;让它在你的家中成为一个令人舒适和享受的角落呢&#xff1f;如果你对此感兴趣&#xff0c;那么我就带你走进阳台装修改造的的世界&#xff0c;一步步了解如何将你的阳台变成梦想中的小天…

rtsp视频在使用unity三维融合播放后的修正

1 rtsp 接入 我们使用unity UE 等三维渲染引擎中使用c编写插件来接入rtsp 视频。同时做融合的时候&#xff0c;和背景的三维颜色要一致&#xff0c;这就要使用视频融合修正技术。包括亮度&#xff0c;对比度&#xff0c;饱和度的修正。在单纯颜色上的修正可以简单使用rgb->…

JavaScript读写15693 ICod2 卡源码

本示例使用设备 &#xff1a; https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-21818769070.11.23eb789efg450Y&id615391857885 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-t…