当前位置: 首页 > news >正文

Linux驱动——设备模型

目录

一、起源

二、新方案

2.1 sysfs:

2.2 uevent

三、代码中自动mknod

四、实例


一、起源

仅devfs,导致开发不方便以及一些功能难以支持:(硬编)

    1. 热插拔(插上usb设备就立马能安装驱动)

    2. 不支持一些针对所有设备的统一操作(如电源管理)

    3. 不能自动mknod

    4. 用户查看不了设备信息

    5. 设备信息硬编码,导致驱动代码通用性差,即没有分离设备和驱动

内核2.6开始引入总线式开发解决这些问题。3.0开始引入设备树。

二、新方案

device+driver结合形成驱动,device内只有设备信息,driver内是一些操作。

uevent机制:sysfs + uevent + udevd(上层app)

uevent是一种通信机制用来解决热插拔的问题。上层还有一个比udevd差一点的mdevd。

2.1 sysfs:

一种用内存模拟的文件系统,系统启动时mount到/sys目录

sysfs用途:(类似于windows的设备管理器)

1. 建立系统中总线、驱动、设备三者之间的桥梁

2. 向用户空间展示内核中各种设备的拓扑图

3. 提供给用户空间对设备获取信息和操作的接口,部分取代ioctl功能

| **sysfs在内核中的组成要素** | **在用户空间/sys下的显示** |

| --------------------------- | -------------------------- |

| 内核对象(kobject)         | 目录                       |

| 对象属性(attribute)       | 文件                       |

| 对象关系(relationship)    | 链接(Symbolic Link)      |

四个基本结构

| **类型**      | **所包含的内容**                   | **内核数据结构**     | **对应/sys项**          |

| ------------- | ------------------------------------------------------- | -------------------- | ----------------------- |

| 设备(Devices) | 设备是此模型中最基本的类型,以设备本身的连接按层次组织       | struct device        | /sys/devices/?/?/.../   |

| 驱动(Drivers) | 在一个系统中安装多个相同设备,只需要一份驱动程序的支持       | struct device_driver | /sys/bus/pci/drivers/?/ |

| 总线(Bus)     | 在整个总线级别对此总线上连接的所有设备进行管理               | struct bus_type      | /sys/bus/?/             |

| 类别(Classes) | 这是按照功能进行分类组织的设备层次树;如 USB 接口和 PS/2 接口的鼠标都是输入设备,都会出现在/sys/class/input/下 | struct class         | /sys/class/?/           |

 最核心的只有这四个,剩下的都是针对某一块,比如block是块设备,fs是文件系统,module是模块。。。。。

目录组织结构:

| **/sys下的子目录** | **所包含的内容**                                             |

| ------------------ | ------------------------------------------------------------ |

| /sys/devices       | 这是内核对系统中所有设备的分层次表达模型,也是/sys文件系统管理设备的最重要的目录结构; |

| /sys/dev           | 这个目录下维护一个按字符设备和块设备的主次号码(major:minor)链接到真实的设备(/sys/devices下)的符号链接文件; |

| /sys/bus           | 这是内核设备按总线类型分层放置的目录结构, devices 中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分; |

| /sys/class         | 这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在/sys/class/input 之下,而不论它们是以何种总线连接到系统。它也是构成 Linux 统一设备模型的一部分; |

| /sys/kernel        | 这里是内核所有可调整参数的位置,目前只有 uevent_helper, kexec_loaded, mm, 和新式的slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于sysctl(/proc/sys/kernel) 接口中; |

| /sys/module        | 这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在/sys/module 中 |

| /sys/power         | 这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重启等。 |


2.2 uevent

 

新方案中bus既提供通信方式,也是device和driver的管理者。

三、代码中自动mknod

```cstruct class *class_create(struct module *owner, const char *name);/** 功能:在/sys/class生成一个目录,目录名由name指定* 参数:struct module *owner - THIS_MODULEconst char *name - 目录名* 返回值  成功:class指针   失败:NULL*//*辅助接口:可以定义一个struct class 的指针变量cls来接受返回值,然后通过IS_ERR(cls)判断是否失败;IS_ERR(cls);成功----------------->0IS_ERR(cls);失败----------------->非0PTR_ERR(cls);来获得失败的返回错误码;*/```
```cvoid class_destroy(struct class *cls)/** 功能:删除class_create生成目录* 参数:struct class *cls - class指针* 返回值*/```
```cstruct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)/** 功能:在/sys/class目录下class_create生成目录再生成一个子目录与该设备相对应,发uevent让应用程序udevd创建设备文件* 参数:struct class *class - class指针struct device *parent - 父对象,一般NULLdev_t devt - 设备号void *drvdata - 驱动私有数据,一般NULLconst char *fmt - 字符串的格式... - 不定参数* 返回值成功:device指针失败:NULL*/```


 

```cvoid device_destroy(struct class *class, dev_t devt)/** 功能:删除device_create生成目录* 参数:struct class *class - class指针dev_t devt - 设备号* 返回值*/```

四、实例

在之前的秒设备上添加自动mknod

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/atomic.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <linux/device.h>
int major = 11;
int minor = 0;
int mysecond_num = 1;struct mysecond_dev
{struct cdev mydev;int second;struct timer_list mytimer;/*Define atomic variables || 1 can open, 0 can not open*/atomic_t openflag;/*automatic create mknod*/struct class *pcls;struct device *pdev;
};struct mysecond_dev gmydev;void timer_func(unsigned long arg)
{struct mysecond_dev *pmydev = (struct mysecond_dev *)arg;pmydev->second++;mod_timer(&pmydev->mytimer, jiffies + HZ * 1);
}int mysecond_open(struct inode *pnode, struct file *pfile)
{struct mysecond_dev *pmydev = NULL;pfile->private_data = (void *) (container_of(pnode->i_cdev, struct mysecond_dev, mydev));pmydev = (struct mysecond_dev *)pfile->private_data;if(atomic_dec_and_test(&pmydev->openflag)){pmydev->mytimer.expires = jiffies + HZ * 1;pmydev->mytimer.function = timer_func;pmydev->mytimer.data = (unsigned long)pmydev;add_timer(&pmydev->mytimer);return 0;}else{atomic_inc(&pmydev->openflag);printk("The device is opened already\n");return -1;}return 0;
}
int mysecond_close(struct inode *pnode, struct file *pfile)
{//printk("mysecond_close\n");/*C90 requires printk after the variable declaration*/struct mysecond_dev *pmydev = (struct mysecond_dev *)pfile->private_data;del_timer(&pmydev->mytimer);atomic_set(&pmydev->openflag,1);return 0;
}ssize_t mysecond_read(struct file *pfile, char __user *puser, size_t size, loff_t *p_pos)
{struct mysecond_dev *pmydev = (struct mysecond_dev *)pfile->private_data;int ret = 0;if(size < sizeof(int)){printk("the expect read size is invalid\n");return -1;}if(size >= sizeof(int)){size = sizeof(int);}ret = copy_to_user(puser, &pmydev->second, size);if(ret){printk("copy to user failed\n");return -1;}return size;
}struct file_operations myops = {.owner = THIS_MODULE,.open = mysecond_open,.release = mysecond_close,.read = mysecond_read,
};int __init mysecond_init(void)
{int ret = 0;dev_t devno = MKDEV(major,minor);/*Apply for device number*/ret = register_chrdev_region(devno, mysecond_num, "mysecond");if(ret){ret = alloc_chrdev_region(&devno, minor, mysecond_num, "mysecond");if(ret){printk("get devno failed\n");return -1;}major = MAJOR(devno);//Easy to miss *****}/*Assign the 'struct cdev' a set of operation functions*/cdev_init(&gmydev.mydev, &myops);/*Add 'struct cdev' to the kernel's data structure*/gmydev.mydev.owner = THIS_MODULE;cdev_add(&gmydev.mydev, devno, mysecond_num);//add to Hash.init_timer(&gmydev.mytimer);/*initialize the atomic variable to 1*/atomic_set(&gmydev.openflag,1);gmydev.pcls = class_create(THIS_MODULE, "mysecond");if(IS_ERR(gmydev.pcls)){printk("class_create failed\n");cdev_del(&gmydev.mydev);unregister_chrdev_region(devno,mysecond_num);return -1;	}gmydev.pdev = device_create(gmydev.pcls,NULL,devno,NULL,"mysec");if(NULL == gmydev.pcls){printk("device_create failed\n");class_destroy(gmydev.pcls);cdev_del(&gmydev.mydev);unregister_chrdev_region(devno,mysecond_num);return -1;	}return 0;
}
void __exit mysecond_exit(void)
{dev_t devno = MKDEV(major,minor);device_destroy(gmydev.pdev,devno);class_destroy(gmydev.pcls);cdev_del(&gmydev.mydev);//printk("mysecond will exit\n");unregister_chrdev_region(devno, mysecond_num);
}
MODULE_LICENSE("GPL");module_init(mysecond_init);
module_exit(mysecond_exit);

 

相关文章:

Linux驱动——设备模型

目录 一、起源 二、新方案 2.1 sysfs: 2.2 uevent 三、代码中自动mknod 四、实例 一、起源 仅devfs&#xff0c;导致开发不方便以及一些功能难以支持&#xff1a;&#xff08;硬编&#xff09; 1. 热插拔&#xff08;插上usb设备就立马能安装驱动&#xff09; 2. 不支持…...

.NET基础加强第一课--面向对象(OO)

.NET基础加强第一课--面向对象&#xff08;OO&#xff09;面向对象什么是类&#xff1f;封装--属性封装字段2&#xff0c; 方法的多个参数封装成一个类3&#xff0c; 把一堆代码封装到一个方法中4&#xff0c; 将一些功能封装到几个类中5&#xff0c; 将一些具有共有功能封装到…...

从Linux源码角度看套接字的Listen及连接队列

今天就从Linux源码的角度看下Server端的Socket在进行listen的时候到底做了哪些事情(基于Linux 3.10内核)&#xff0c;当然由于listen的backlog参数和半连接hash表以及全连接队列都相关&#xff0c;在这里也一块讲了。 Server端Socket需要Listen 众所周知&#xff0c;一个Serv…...

cesium: 显示闪烁的点(004)

第004个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置闪烁的点。主要是介绍entity>point 相关的属性设置 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共107行)相关API参考:专栏目标示例效果 配…...

常见代码审计工具,代码审计为什么不能只用工具?

代码审计是一种发现程序漏洞&#xff0c;安全分析为目标的程序源码分析方式。今天主要分享的是几款常用的代码审计工具&#xff0c;以及代码审计工具有哪些优缺点&#xff1f; 代码审计工具 seay代码审计工具&#xff0c;是一款开源的利用C#开发的一款代码审计工具。主要有SQ…...

es8集群模式部署

准备3台机器 192.168.1.41 192.168.1.42 192.168.1.43因为es集群有几个节点&#xff0c;所以我对应node1&#xff0c;node2&#xff0c;node3.这几个名称并不是主机名&#xff0c;而是es节点名称 2. 开始部署&#xff0c;基础配置 (三台都做) systemctl stop firewalld syste…...

OAuth2

1.什么是OAuth2 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时&#xff0c;任何第三方都可以使用OAUTH认证服务&#xff0c;任何服务提供商都可以实现自身的OAUTH认证服务&#xff0c;因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP、JavaScript&…...

一、简单排序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、Comparable接口介绍 1.描述 2.Comparable使用 二、冒泡排序 1.排序原理 2.冒泡排序实现 2.1 冒泡排序API 2.2 冒泡排序实现 3.冒泡排序时间复杂度 三…...

慢SQL出现原因、优化、开启慢查询日志

文章目录慢SQL:出现原因&#xff1a;解决方式&#xff1a;开启慢查询日志&#xff1a;慢SQL: 出现原因&#xff1a; &#xff08;1&#xff09;数据库表索引设置不合理 &#xff08;2&#xff09;SQL语句有问题&#xff0c;需要优化 解决方式&#xff1a; &#xff08;1&am…...

要理解网络,其实不就是理解这三张表吗

我们如果要理解数据是如果在网络世界中穿梭的&#xff0c;那其实只要了解其中的三张表就可以了。这三张表分别为路由表、转发表、ARP 表。 假设我们用聊天工具聊天的时候&#xff0c;我在北京&#xff0c;你在广东&#xff0c;当我给你发送一条消息的时候。搭载这这条消息的数据…...

Java异常架构与异常关键字

Java异常简介 Java异常是Java提供的一种识别及响应错误的一致性机制。 Java异常机制可以使程序中异常处理代码和正常业务代码分离&#xff0c;保证程序代码更加优雅&#xff0c;并提高程序健壮性。在有效使用异常的情况下&#xff0c;异常能清晰的回答what, where, why这3个问…...

【阅读笔记】SecureML: A System for ScalablePrivacy-Preserving Machine Learning

1. Motivation 针对机器学习中的出现的数据隐私泄露的风险&#xff0c;提出了线性回归、逻辑回归以及简单神经网络的隐私保护模型。 2. Contributions 2.1 为线性回归、逻辑回归以及神经网络设计安全计算协议 2.1.1.1 线性回归 线性回归损失函数为&#xff1a; , 采用SG…...

【2023美赛】C题Wordle预测27页中文论文及Python代码详解

【2023美赛】C题Wordle预测27页中文论文及Python详解 相关链接 &#xff08;1&#xff09;2023年美赛C题Wordle预测问题一建模及Python代码详细讲解 &#xff08;2&#xff09;2023年美赛C题Wordle预测问题二建模及Python代码详细讲解 &#xff08;3&#xff09;2023年美赛C题…...

【C++修行之路】STL——模拟实现string类

文章目录前言类框架构造与析构c_str迭代器操作符重载[]&#xff1a;&#xff1a;> > < < !:reverse与resizereverseresizepush_back与append复用实现insert和erasec_str与流插入、流提取eraseswap(s1,s2)与s1.swap(s2)结语前言 这次我们分几个部分来实现string类…...

CorelDRAW2023最新版序列号使用教程

CorelDRAW2023用起来非常顺手&#xff0c;旨在为用户解决因在工作上带来的问题&#xff0c;在业内可谓享有极高的声誉&#xff0c;是业内人士常用的一款工具&#xff0c;有了它&#xff0c;可以更好的帮助用户把握好各个方面的细节&#xff0c;减少其他方面的失误&#xff0c;让…...

【一天一门编程语言】Python 语言程序设计极简教程

文章目录 Python 语言程序设计极简教程一、Python语言简介1.1 Python的优势1.2 Python的应用二、Python基础语法2.1 Python基础2.1.1 注释2.1.2 变量2.1.3 运算符2.1.4 控制流2.1.5 函数2.2 Python数据类型2.2.1 数字2.2.2 字符串2.2.3 列表2.2.4 元组2.2.4.1 元组的基本操作创…...

14、KL散度

KL 散度&#xff0c;是一个用来衡量两个概率分布的相似性的一个度量指标。 现实世界里的任何观察都可以看成表示成信息和数据&#xff0c;一般来说&#xff0c;我们无法获取数据的总体&#xff0c;我们只能拿到数据的部分样本&#xff0c;根据数据的部分样本&#xff0c;我们会…...

TypeError: load() missing 1 required positional argument: ‘Loader‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

【设计模式】 观察者模式介绍及C代码实现

【设计模式】 观察者模式介绍及C代码实现 背景 在软件构建过程中&#xff0c;我们需要为某些对象建立一种“通知依赖关系”&#xff0c;即一个对象&#xff08;目标对象&#xff09;的状态发生改变&#xff0c;所有的依赖对象&#xff08;观察者对象&#xff09;都将得到通知。…...

01-Maven基础-简介安装、基本使用(命令)、IDEA配置、(写jar,刷新自动下载)、依赖管理

文章目录0、Maven1、Maven 简介2、Maven 安装配置安装配置步骤3、Maven 基本使用Maven 常用命令Maven 生命周期IDEA 配置 MavenMaven 坐标详解IDEA 创建 Maven 项目IDEA 导入 Maven 项目配置 Maven-Helper 插件 (非常实用的小插件)依赖管理使用坐标导入 jar 包依赖范围0、Maven…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

React核心概念:State是什么?如何用useState管理组件自己的数据?

系列回顾&#xff1a; 在上一篇《React入门第一步》中&#xff0c;我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目&#xff0c;并修改了App.jsx组件&#xff0c;让页面显示出我们想要的文字。但是&#xff0c;那个页面是“死”的&#xff0c;它只是静态…...