【linux kernel】杂项(misc)设备驱动总结

文章目录

    • 一、杂项设备简介
    • 二、杂项设备API
      • 1、注册杂项设备
      • 2、注销杂项设备
      • 3、杂项设备模块助手函数
    • 三、杂项设备初始化
    • 四、杂项设备示例
    • 五、杂项设备和字符设备


👉相关文件:

  • drivers/char/misc.c
  • include/linux/miscdevice.h

一、杂项设备简介

Linux 内核中的杂项设备(Miscellaneous Devices)是一种通用的设备类型,用于表示那些不适合其他设备类型的设备。这些设备通常是不规则的,没有标准的通信协议或接口。杂项设备提供了一种灵活的机制,允许我们将不同类型的设备注册为杂项设备,并通过统一的接口在用户空间访问它们。

在 Linux 内核中,杂项设备通过struct miscdevice结构来表示:

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;
};
  • minor: 杂项设备的次设备号。如果将 MISC_DYNAMIC_MINOR 分配给此字段,内核将动态分配次设备号。

  • name: 杂项设备的名称,用于在 /dev 文件系统中创建设备节点。

  • fops: 指向包含设备操作的 struct file_operations 结构的指针,定义了对该设备进行的操作。

  • list: 用于将杂项设备链接到内核中的杂项设备列表中。

  • parent: 指向父设备的指针,如果杂项设备与其他设备相关联,则指向该设备的父设备。

  • this_device: 指向表示该杂项设备的 struct device 结构的指针。

  • groups: 用于定义设备属性的指针数组。属性组定义了设备的属性,例如 sysfs 上的属性。

  • nodename: 杂项设备节点的名称,通常与 name 字段相同。此字段用于在 /sys 文件系统中创建设备节点。

  • mode: 设备节点的权限模式,指定了用户对设备节点的访问权限。

struct miscdevice 提供了一种将设备注册为杂项设备的机制,并指定了设备的名称、操作以及其他相关属性。杂项设备在 /dev 目录下创建,但是它们的名字与其驱动程序关联,而不是与设备类型直接关联。因此,同一类型的设备可能具有不同的名称,取决于它们所使用的驱动程序。

二、杂项设备API

在内核中,关于杂项设备提供的驱动API较少,仅包含两个API。

1、注册杂项设备

int misc_register(struct miscdevice *misc)
  • struct miscdevice *misc:杂项设备结构

该函数用于向内核注册一个杂项设备。如果次设备号设置为 MISC_DYNAMIC_MINOR,则会分配一个次设备号,并将其放置在结构体的 minor 字段中。对于其他情况,使用请求的次设备号。

传递的结构体被链接到内核中,并且在注销之前可能不会被销毁。默认情况下,对设备的 open() 系统调用会将 file->private_data 设置为指向该结构体。驱动程序不需要在 fops 中包含 open 函数。

成功时返回零,失败时返回负的 errno 代码。

2、注销杂项设备

int misc_deregister(struct miscdevice *misc)
  • struct miscdevice *misc:杂项设备结构

该函数用于注销之前使用 misc_register() 成功注册的杂项设备。

3、杂项设备模块助手函数

提供了一个模块助手函数module_misc_device(),在编写杂项设备驱动时,可以直接使用该宏函数替换模块的init和exit操作。

三、杂项设备初始化

在Linux内核中都会支持杂项设备,在内核启动过程中,会调用misc_init()完成杂项设备相关的初始化操作:

static int __init misc_init(void)
{
	int err;

#ifdef CONFIG_PROC_FS
	proc_create("misc", 0, NULL, &misc_proc_fops);
#endif
	misc_class = class_create(THIS_MODULE, "misc");
	err = PTR_ERR(misc_class);
	if (IS_ERR(misc_class))
		goto fail_remove;

	err = -EIO;
	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
		goto fail_printk;
	misc_class->devnode = misc_devnode;
	return 0;

fail_printk:
	printk("unable to get major %d for misc devices\n", MISC_MAJOR);
	class_destroy(misc_class);
fail_remove:
	remove_proc_entry("misc", NULL);
	return err;
}
subsys_initcall(misc_init);

上述代码主要完成以下三个操作:

  • 使用proc_create()创建一个名为 “misc” 的 proc 文件,使用指定的文件操作 misc_proc_fops
  • 使用class_create()创建一个名为 “misc” 的设备类。
  • register_chrdev()注册字符设备

上述代码的目的是初始化杂项设备,包括创建 proc 文件、创建设备类、注册字符设备等。

四、杂项设备示例

我们通常通过以下步骤来创建和注册杂项设备:

  • 1、定义和初始化 miscdevice 结构。
  • 2、调用 misc_register() 函数注册杂项设备。
  • 3、在驱动模块的退出函数中调用 misc_deregister() 函数注销杂项设备。

例如下例代码:

#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "my_misc_device"

static int my_misc_open(struct inode *inode, struct file *file)
{
    // Open device logic
    return 0;
}

static int my_misc_release(struct inode *inode, struct file *file)
{
    // Release device logic
    return 0;
}

static ssize_t my_misc_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
{
    // Read from device logic
    return 0;
}

static ssize_t my_misc_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
    // Write to device logic
    return len;
}

static const struct file_operations my_misc_fops = {
    .owner = THIS_MODULE,
    .open = my_misc_open,
    .release = my_misc_release,
    .read = my_misc_read,
    .write = my_misc_write,
};

static struct miscdevice my_misc_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &my_misc_fops,
};

static int __init my_misc_init(void)
{
    int ret = misc_register(&my_misc_device);
    if (ret) {
        printk("Failed to register misc device\n");
        return ret;
    }
    printk("Registered misc device successfully\n");
    return 0;
}

static void __exit my_misc_exit(void)
{
    misc_deregister(&my_misc_device);
    printk("Deregistered misc device\n");
}

module_init(my_misc_init);
module_exit(my_misc_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Iriczhao");
MODULE_DESCRIPTION("A simple miscellaneous device driver");

五、杂项设备和字符设备

在 Linux 内核中,杂项设备(misc device)和字符设备(character device)是两种不同类型的设备。在内核中的实现和使用方式略有不同。

  1. 杂项设备(Miscellaneous Devices)

    • 杂项设备是一种比较通用的设备类型,用于表示不适合其他设备类型的设备。
    • 这些设备通常是不规则的,没有标准的通信协议或接口。
    • 杂项设备在 /dev 目录下创建,但是它们的名字与其驱动程序关联,而不是与设备类型直接关联。
    • 在内核中,杂项设备通过 miscdevice 结构来表示,该结构包含了设备的名称、设备号、文件操作等信息。
    • 创建和注册杂项设备通常涉及使用 misc_register()misc_deregister() 等函数。
  2. 字符设备(Character Devices)

    • 字符设备是一种基本的设备类型,用于处理以字符为单位的数据流。
    • 这些设备通常是顺序访问的,没有固定的大小或边界。
    • 字符设备在 /dev 目录下创建,并且其名称直接与设备类型相关联。
    • 在内核中,字符设备通过 cdev 结构来表示,该结构包含了设备的文件操作等信息。
    • 创建和注册字符设备通常涉及使用 cdev_add()cdev_del() 等函数。

总的来说,杂项设备适用于那些不符合标准设备模型的设备,而字符设备则适用于以字符流形式进行通信的设备。在编写内核驱动程序时,我们可以根据设备的特性选择适当的设备类型。

参考链接:
https://docs.kernel.org/driver-api/misc_devices.html?highlight=misc_register#c.misc_register

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Idea + maven 搭建 SSH (struts2 +hibernate5 + spring5) 环境

org.apache.struts struts2-core 2.3.35 org.apache.struts struts2-spring-plugin 2.3.35 org.apache.struts struts2-json-plugin 2.3.8 1.4 配置Java EE 坐标依赖 这里可以引入 servlet api&#xff0c;jstl 标签库等一系列工具 javax.servlet javax.servlet-api …

c语言实现贪吃蛇小游戏————附全代码!!!

目录 1.Win32 API 1.1控制台应用程序 1.2控制台的名称&#xff0c;控制台窗口大小 1.3设置控制台光标位置 COORD - 光标坐标 GetStdHandle - 获取句柄 SetConsoleCursorPosition - 设置光标位置 封装一个设置光标的函数 1.4设置控制台光标的属性 CONSOLE_CURSOR_INFO …

【第13章】spring-mvc之validator

文章目录 前言一、准备1. 引入库2. add.jsp3. show.jsp 二、代码部分1.实体类2. 控制器类3. 效果4. 展示 总结 前言 【第20章】spring-validator 虽然前面已经在spring介绍过&#xff0c;但是为了保证代码可用&#xff0c;还是会从头讲到尾&#xff0c;尽量把关键点列出来讲给…

微服务架构中的挑战及应对方式:Outbox 模式

使用 Outbox 模式保持微服务数据一致性 在一个由许多小型服务组成的系统中保持数据一致性是困难的&#xff0c;因为它们分散在各处。以下是一些常见问题以及如何处理它们的方法&#xff1a;当服务发送消息时&#xff0c;同时更新数据库和发送消息是棘手的问题。 在微服务中发出…

【Qt 开发基础体系】Qt信号与槽机制

文章目录 1.Qt 信号与槽机制原理&#xff08;Signal & Slot&#xff09;2. QObject 类 connect 的介绍3. 信号与槽机制连接方式4. 信号和槽机制优势及其效率&#xff1a;3. 信号与槽机制应用 1.Qt 信号与槽机制原理&#xff08;Signal & Slot&#xff09; &#x1f42…

通过AOP实现项目中业务服务降级功能

最近项目中需要增强系统的可靠性&#xff0c;比如某远程服务宕机或者网络抖动引起服务不可用&#xff0c;需要从本地或者其它地方获取业务数据&#xff0c;保证业务的连续稳定性等等。这里简单记录下业务实现&#xff0c;主要我们项目中调用远程接口失败时&#xff0c;需要从本…

《武林秘籍》——闪侠惠递如何让消费者寄快递更安心!

现如今&#xff0c;网上下单寄快递的便利性让众多人享受到了电商物流飞速发展带来的红利性。今天小编直接介绍一款寄快递特别省钱的利器&#xff0c;就是利用闪侠惠递来寄快递。闪侠惠递寄快递&#xff0c;真正的实现了便宜寄快递发物流的便捷性&#xff0c;开创了低价发快递的…

【汇总】虚拟机网络不通(Xshell无法连接虚拟机)排查方法

搜索关键字关键字关键字&#xff1a;虚拟机虚拟机虚拟机连接失败、虚拟机无法连接、Xshell连接失败、ping baidu.com失败、静态IP设置 Kali、CentOS、远程连接 描述&#xff1a;物理机无法连接虚拟机&#xff1b;虚拟机无法访问百度&#xff0c;虚拟机无法访问baidu.com 虚拟机…

Logstash分析MySQL慢查询日志实践

删除匹配到的行&#xff0c;当前行信息不记录到message中

可视化面板布局适配屏幕-基于 flexible.js + rem 智能大屏适配

可视化面板布局适配屏幕-基于 flexible.js rem 智能大屏适配 VScode 安装cssrem插件引入flexible.js在之后的开发都使用rem为单位&#xff0c;安装cssrem插件就是为了快捷将px转为rem我们的设计稿是1920px&#xff0c;设置最小宽度为1024px&#xff0c;最后&#xff0c;我们可…

JavaScript异步编程——05-回调函数

我们在前面的文章《JavaScript 基础&#xff1a;异步编程/单线程和异步》中讲过&#xff0c;Javascript 是⼀⻔单线程语⾔。早期我们解决异步场景时&#xff0c;⼤部分情况都是通过回调函数来进⾏。 &#xff08;如果你还不了解单线程和异步的概念&#xff0c;可以先去回顾上一…

SlowFast报错:ValueError: too many values to unpack (expected 4)

SlowFast报错&#xff1a;ValueError: too many values to unpack (expected 4) 报错细节 File "/home/user/yuanjinmin/SlowFast/tools/visualization.py", line 81, in run_visualizationfor inputs, labels, _, meta in tqdm.tqdm(vis_loader): ValueError: too …

流星烛台如何交易?Anzo Capital昂首资本3步盈利收场

各位投资者通过之前的文章可以准确的辨认出什么是流星烛台了&#xff0c;但是各位投资者一旦遇到流星图案知道怎么交易吗?其实一点都不困难&#xff0c;只要掌握住流星图案的交易真棒&#xff0c;Anzo Capital昂首资本3步就可以盈利收场。 首先&#xff0c;投资者需要确定图…

文件下载出现 IOExpcetion: closed

异常原因截图 : 异常代码位置 : 出现的原因是 使用 try-with-resources, downloadFile 方法执行完毕, 文件流被关闭了...导致前面读取文件字节, 异常提示已经关闭... try (Response response OkHttpUtils.getInstance().client.newCall(new Request.Builder().url(fileUrl)…

Yolov8实现loopy视频识别

1、前言 loopy是一个非常可爱的动漫角色&#xff08;可爱粉色淀粉肠&#xff09;&#xff0c;闲来无事&#xff0c;打算用yolov8训练一个模型对loopy进行识别。 2、准备工作 先在网络上搜寻很多loopy的图片&#xff0c;然后将图片导入Lablel Studio软件进行标注&#xff0c;并…

第1章.STM32单片机入门知识介绍

目录 0. 《STM32单片机自学教程》专栏 1.1 嵌入式系统简介 1.1.1 什么是嵌入式系统 1.1.2 嵌入式系统的特点 1.1.3 嵌入式系统的应用领域 1.2 单片机基本概念 1.3 ARM简介 1.3.1 ARM公司简介 1.3.2 ARM处理器简介 1.4 STM32简介 1.4.1 基于Cortex内核的MCU 1.4.…

springMVC入门学习

目录 1、 什么是springmvc 2、springmvc工作流程 3、 springmvc快速入门&#xff08;XML版本&#xff09; 4、加载自定义目录下的springmvc.xml配置文件 5、 解析器InternalResourceViewResolver 6、 映射器BeanNameUrlHandlerMapping 7、 适配器SimpleControllerHandle…

【算法-程序的灵魂#谭浩强配套】(适合专升本、考研)

无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 完整资料如下&#xff1a; 1.一个程序主要包括以下两方面信息&#xff1a;程…

React:Router-1.BrowserRouter组件式

使用步骤 安装 react-router-dom 依赖 $ npm install react-router-dom6导入 BrowserRouter, Link, Routes, Route 对象 import {BrowserRouter, Link, Routes, Route} from react-router-dom;3.BrowserRouter&#xff1a;history模式路由&#xff1b; HashRouter&#xff1…

Flask gevent启动报错UnicodeDecodeError

文章目录 环境代码报错Track解决思路 环境 acondana 24.1.2python 3.7.13 32bitflask 2.2.3gevent 21.8.0 代码 port 7236 logging.basicConfig(levellogging.INFO, # 控制台打印的日志级别filename./logs/app.log, # 将日志写入log_new.log文件中filemodea, # 模式&…