linux 驱动——杂项设备驱动

news2024/9/22 1:08:50

杂项设备驱动

在 linux 中,将无法归类的设备定义为杂项设备。
相对于字符设备来说,杂项设备的主设备号固定为 10,而字符设备不管是动态分配还是静态分配设备号,都会消耗一个主设备号,比较浪费主设备号。
杂项设备会自己调用 class_create()device_create() 来自动创建设备节点。所以可以将杂项设备看成是字符设备的一种。但是比平时写的字符设备降低了难度并节约了主设备号。

杂项设备的次设备号 minor 一般使用宏 MISC_DYNAMIC_MINOR,表示自动分配次设备号。杂项设备主要依赖次设备号来管理不同的杂项设备。

杂项设备的头文件为 #include <linux/miscdevice.h>

数据类型

struct miscdevice  {
	int minor;
	const char *name;
	const struct file_operations *fops;
	struct list_head list;
	struct device *parent;
	struct device *this_device;
	const struct attribute_group **groups;
	const char *nodename;
	umode_t mode;
};

API

int misc_register(struct miscdevice *misc);
void misc_deregister(struct miscdevice *misc);

驱动程序

#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>
#include <linux/miscdevice.h>

#define CHRDEVBASE_NAME "misc_test1" /* 设备名 */

static char write_buf[100];
static char read_buf[100];

static char *string_test = "kernel data this tyustli test";

static int miscdev_open(struct inode *inode, struct file *file)
{
    printk("k: miscdev open\r\n");

    return 0;
}

static ssize_t miscdev_read(struct file *file, char __user *buf, size_t count,
                            loff_t *ppos)
{
    unsigned long ret = 0;

    printk("k: miscdev read\r\n");
    memcpy(read_buf, string_test, strlen(string_test));

    ret = copy_to_user(buf, 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 miscdev_write(struct file *file, const char __user *buf,
                             size_t count, loff_t *ppos)
{
    unsigned long ret = 0;

    printk("k: miscdev write\r\n");

    ret = copy_from_user(write_buf, buf, count);
    if (ret == 0) {
        printk("k: write data success write data is: %s\r\n", write_buf);
    } else {
        printk("k: write data failed ret = %ld\r\n", ret);
    }

    return count;
}

static int miscdev_release(struct inode *inode, struct file *file)
{
    printk("k: miscdev release\r\n");

    return 0;
}

static struct file_operations miscdev_fops = {
    .owner = THIS_MODULE,
    .open = miscdev_open,
    .read = miscdev_read,
    .write = miscdev_write,
    .release = miscdev_release,
};

static struct miscdevice miscdevice_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = CHRDEVBASE_NAME,
    .fops = &miscdev_fops,
};

static int __init miscdev_init(void)
{
    int err = 0;

    err = misc_register(&miscdevice_dev);
    if (err < 0) {
        printk("k: misc register err = %d\r\n", err);
        goto err_misc;
    }

    printk("k: misc module init!\r\n");

err_misc:
    return err;
}

static void __exit miscdev_exit(void)
{
    misc_deregister(&miscdevice_dev);

    printk("k: misc module exit!\r\n");
}

module_init(miscdev_init);
module_exit(miscdev_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;
}

模块使用

查看字符设备 cat /proc/devices

~ # cat /proc/devices 
Character devices:
  1 mem
  2 pty
  3 ttyp
  4 /dev/vc/0
  4 tty
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 29 fb
 90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 ttyAMA
226 drm
249 rpmb
250 usbmon
251 ptp
252 pps
253 rtc
254 gpiochip

Block devices:
  8 sd
 31 mtdblock
 65 sd
 66 sd
 67 sd
 68 sd
 69 sd
 70 sd
 71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
254 virtblk
259 blkext
~ # 

查看设备节点

ls /dev

在这里插入图片描述

模块安装

modprobe my_module

模块使用

lib/modules/6.5.7+/my_app /dev/misc_test1 1
lib/modules/6.5.7+/my_app /dev/misc_test1 2

模块运行日志

~ # /lib/modules/6.5.7+/my_app /dev/misc_test1 1
k: miscdev open
k: miscdev read
k: read data success
u: read data:kernel data this tyustli test
k: miscdev release
~ # /lib/modules/6.5.7+/my_app /dev/misc_test1 2
k: miscdev open
k: miscdev write
k: write data success write data is: user data!
k: miscdev release

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

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

相关文章

PyCharm添加自动函数文档注释

目录 1、背景2、开启PyCharm自动函数文档注释 1、背景 规范的函数文档注释有助于他人理解代码&#xff0c;便于团队协作、提高效率。但如果我们自己手写函数文档注释将非常耗时耗力。PyCharm安装后默认没有开启自动化函数文档注释&#xff0c;需要我们开启 2、开启PyCharm自动…

JavaWeb笔记之前端开发JavaScript

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

LVM Sequential Modeling Enables Scalable Learning for Large Vision Models

LVM: Sequential Modeling Enables Scalable Learning for Large Vision Models TL; DR&#xff1a;本文提出一种纯视觉的序列建模方法 LVM&#xff0c;不需要任何文本数据。通过 visual sentences 的形式&#xff0c;统一图像/视频/标注/3D数据&#xff0c;使用 VQGAN 将视觉…

网上平台交易伦敦金靠谱吗?

随着科技的发展&#xff0c;网络交易已经成为了我们生活中的一部分。在金融领域&#xff0c;许多投资者也早已开始转向在线交易平台进行投资交易&#xff0c;其中就包括伦敦金。然而&#xff0c;面对众多的网上交易平台&#xff0c;投资者们往往会产生这样的疑问&#xff1a;“…

4.3 C++对象模型和this指针

4.3 C对象模型和this指针 4.3.1 成员变量和成员函数分开存储 在C中&#xff0c;类内的成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 #include <iostream>class Person { public:Person() {mA 0;} //非静态成员变量占对象空间int mA;//静态成员变量…

【spark】spark内核调度(重点理解)

目录 spark内核调度DAGDAG的宽窄依赖和阶段划分内存迭代计算面试题Spark是怎样做内存计算的&#xff1f;DAG的作用是什么&#xff1f;Stage阶段划分的作用&#xff1f;Spark为什么比MapReduce快 spark并行度如何设置并行度&#xff1a;spark.default.parallelism集群中如何规划…

P1 H264码流结构分析 (上)

目录 前言 01 什么是码流结构 02 H264帧类型的区别 03 片slice 前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525…

官方指定Jmeter配置JVM堆内存方式

1.概述 在使用Jmeter做性能测试过程中&#xff0c;可能会应为默认设置的堆内存值较小出现堆内存溢出问题&#xff0c;此时解决的方式有两种&#xff0c;分布式测试和调大堆内存。下面介绍官方推荐调整堆内存方法。 2.调整Jmeter堆内存 2.1.介绍官方推荐堆内存调整方法(jmete…

IDEA Community html文件里的script标签没有syntax highlighting的解决方案

在网上找到的解决方法有的是针对Ultimate版本才可以下载的plugin&#xff0c;对我所用的Community版本无法生效&#xff0c;找了一圈最后在stackoverflow上找到一个有效的方案&#xff0c;给需要的小伙伴分享一下&#xff1a;IntelliJ Community Edition: Javascript syntax hi…

Jenkins 执行远程脚本的插件—SSH2 Easy

SSH2 Easy 是什么&#xff1f; SSH2 Easy 是一个 Jenkins 插件&#xff0c;它用于在 Jenkins 构建过程中通过 SSH2 协议与远程服务器进行交互。通过该插件&#xff0c;用户可以在 Jenkins 的构建过程中执行远程命令、上传或下载文件、管理远程服务器等操作。 以下是 SSH2 Eas…

7-4 JAVA-水仙花数(Java for PTA)

水仙花数是指一个N位正整数&#xff08;7≥N≥3&#xff09;&#xff0c;它的每个位上的数字的N次幂之和等于它本身。例如&#xff1a;153135333。 要求编写程序&#xff0c;计算所有N位水仙花数。 输入格式: 输入一个正整数N&#xff08;3≤N≤7&#xff09;。 输出格式: …

java并发编程四 Monitor 概念,api介绍与线程状态转换

Monitor 概念 Java 对象头 以 32 位虚拟机为例子&#xff1a; 普通对象 数组对象 其中 Mark Word 结构为 64 位虚拟机 Mark Word 小故事 故事角色 老王 - JVM小南 - 线程小女 - 线程房间 - 对象房间门上 - 防盗锁 - Monitor房间门上 - 小南书包 - 轻量级锁房间门上 -…

Elasticsearch常见面试题

文章目录 1.简单介绍下ES&#xff1f;2.简单介绍当前可以下载的ES稳定版本&#xff1f;3.安装ES前需要安装哪种软件&#xff1f;4.请介绍启动ES服务的步骤&#xff1f;5.ES中的倒排索引是什么&#xff1f;6. ES是如何实现master选举的&#xff1f;7. 如何解决ES集群的脑裂问题8…

本地文件内容搜索神器AnyTXT Searcher如何搭建与远程访问

文章目录 前言1. AnyTXT Searcher1.1 下载安装AnyTXT Searcher 2. 下载安装注册cpolar3. AnyTXT Searcher设置和操作3.1 AnyTXT结合cpolar—公网访问搜索神器3.2 公网访问测试 4. 固定连接公网地址 前言 你是否遇到过这种情况&#xff0c;异地办公或者不在公司&#xff0c;想找…

ubuntu qt 源码编译

官方源码下载地址 : 源码地址 选择要下载的版本 dmg结尾的是MacOS系统里使用的Qt库&#xff0c;qt-everywhere-opensource-src-4.7.0是Qt源码包&#xff0c;有zip和tar.gz两个压缩格式的&#xff0c;两个内容是一样的&#xff0c;只是zip一般在Windows下比较流行&#xff0c;…

【100个Cocos实例】快要圣诞节了,给大家支个招!

引言 Mask遮罩组件的一些简单实例 在游戏开发中常常需要在UI界面上展示玩家的头像或者Logo&#xff0c;通常都会是正方形。 偶尔也会有一些奇形怪状的需求&#xff0c;例如五边形、六边形、心形等等。 本文将介绍一下在Cocos游戏开发中Mask遮罩组件的一些简单实例&#xff…

九州未来向开放原子开源基金会捐赠OpenV2X,共建繁荣开源生态

12月16日&#xff0c;以“一切为了开发者”为主题的开放原子开发者大会在无锡成功举办。会上&#xff0c;九州未来将OpenV2X车路协同开源项目正式捐赠给开放原子开源基金会&#xff0c;并签署项目捐赠协议&#xff0c;通过开源共创的方式&#xff0c;携手开源伙伴共同打造车路协…

[微服务 ]微服务集成中的3个常见缺陷,以及如何避免它们

微服务风靡一时。他们有一个有趣的价值主张&#xff0c;即在与多个软件开发团队共同开发的同时&#xff0c;将软件快速推向市场。因此&#xff0c;微服务是在扩展您的开发力量的同时保持高敏捷性和快速的开发速度。 简而言之&#xff0c;您将系统分解为微服务。分解并不是什么新…

RLAIF方法与传说中的函数‘Q‘,揭露OpenAI那不为人知的Qstar计划

早晨刚起来,看群里新哥转了这个帖子: 帖子不长,但是基本是爆炸类的新闻了!这个应该也就是Sam之前被董事会诟病的所谓隐瞒了的真相! 在讲解这个帖子之前,先要普及2个概念: 1- RLAIF: 不是TGIF,虽然今天确实是周五 RLAIF是Google今年9月新出来的论文,论文…

智能优化算法应用:基于堆优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于堆优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于堆优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.堆优化算法4.实验参数设定5.算法结果6.参考文…