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

linux 设备模型之设备

在最低层, Linux 系统中的每个设备由一个 struct device 代表:
struct device { struct device *parent; struct kobject kobj; char bus_id[BUS_ID_SIZE];
struct bus_type *bus; struct device_driver *driver; void *driver_data; void
(*release)(struct device *dev); /* Several fields omitted */ };
有许多其他的 struct device 成员只对设备核心代码感兴趣. 但是, 这些成员值得了解:
struct device *parent

设备的 "parent" 设备 -- 它所附着到的设备. 在大部分情况, 一个父设备是某种
总线或者主控制器. 如果 parent 是 NULL, 设备是一个顶层设备, 这常常不是你
所要的.
struct kobject kobj;
代表这个设备并且连接它到层次中的 kobject. 注意, 作为一个通用的规则,
device->kobj->parent 等同于 device->parent->kobj.
char bus_id[BUS_ID_SIZE];
唯一确定这个总线上的设备的字符串. PCI 设备, 例如, 使用标准的 PCI ID 格式,
包含域, 总线, 设备, 和功能号.
struct bus_type *bus;
确定设备位于哪种总线.
struct device_driver *driver;
管理这个设备的驱动; 我们查看 struct device_driver 在下一节.
void *driver_data;
一个可能被设备驱动使用的私有数据成员.
void (*release)(struct device *dev);
当对这个设备的最后引用被去除时调用的方法; 它从被嵌入的 kobject 的
release 方法被调用. 注册到核心的所有的设备结构必须有一个 release 方法,
否则内核打印出慌乱的抱怨.
最少, parent, bus_id, bus, 和 release 成员必须在设备结构被注册前设置.

设备注册

通常的注册和注销函数在:
int device_register(struct device *dev);
void device_unregister(struct device *dev);
我们已经见到 lddbus 代码如何注册它的总线类型. 但是, 一个实际的总线是一个设备并
且必须单独注册. 为简单起见, lddbus 模块只支持一个单个虚拟总线, 因此这个驱动在
编译时建立它的设备:
static void ldd_bus_release(struct device *dev)
{
printk(KERN_DEBUG "lddbus release\n");

}
struct device ldd_bus = {
.bus_id = "ldd0",
.release = ldd_bus_release
};
这是顶级总线, 因此 parent 和 bus 成员留为 NULL. 我们有一个简单的, no-op
release 方法, 并且, 作为第一个(并且唯一)总线, 它的名子时 ldd0. 这个总线设备被
注册, 使用:
ret = device_register(&ldd_bus);
if (ret)
printk(KERN_NOTICE "Unable to register ldd0\n");
一旦调用完成, 新总线可在 sysfs 中 /sys/devices 下面见到. 任何加到这个总线的设
备接着在 /sys/devices/ldd0 下显示.

设备属性

sysfs 中的设备入口可有属性. 相关的结构是:
struct device_attribute {
struct attribute attr;
ssize_t (*show)(struct device *dev, char *buf);
ssize_t (*store)(struct device *dev, const char *buf,
size_t count);
};
这些属性结构可在编译时建立, 使用这些宏:
DEVICE_ATTR(name, mode, show, store);
结果结构通过前缀 dev_attr_ 到给定名子上来命名. 属性文件的实际管理使用通常的函
数对来处理:
int device_create_file(struct device *device, struct device_attribute *entry);
void device_remove_file(struct device *dev, struct device_attribute *attr);
struct bus_type 的 dev_attrs 成员指向一个缺省的属性列表, 这些属性给添加到总线
的每个设备创建.

设备结构嵌入

设备结构包含设备模型核心需要的来模型化系统的信息. 大部分子系统, 但是, 跟踪关于
它们驻留的设备的额外信息. 结果, 对设备很少由空设备结构所代表; 相反, 这个结构,
如同 kobject 结构, 常常是嵌入一个更高级的设备表示中. 如果你查看 struct pci_dev

的定义或者 struct usb_device 的定义, 你会发现一个 struct device 埋在其中. 常常
地, 低层驱动甚至不知道 struct device, 但是有例外.
lddbus 驱动创建它自己的设备类型( struct ldd_device ) 并且期望单独的设备驱动来
注册它们的设备使用这个类型. 它是一个简单结构:
struct ldd_device {
char *name;
struct ldd_driver *driver;
struct device dev;
};
#define to_ldd_device(dev) container_of(dev, struct ldd_device, dev);
这个结构允许驱动提供一个实际的名子给设备( 这可以清楚地不同于它的总线 ID, 存储
于设备结构) 以及一个这些驱动信息的指针. 给真实设备的结构常常还包含关于供应者信
息, 设备型号, 设备配置, 使用的资源, 等等. 可以在 struct pci_dev (<linux/pci.h>)
或者 struct usb_device (<linux/usb.h>) 中找到好的例子. 一个方便的宏
( to_ldd_device ) 也为 struct ldd_device 定义, 使得容易转换指向被嵌入的结构的
指针为 ldd_device 指针.
lddbus 输出的注册接口看来如此:
int register_ldd_device(struct ldd_device *ldddev)
{
ldddev->dev.bus = &ldd_bus_type;
ldddev->dev.parent = &ldd_bus;
ldddev->dev.release = ldd_dev_release;
strncpy(ldddev->dev.bus_id, ldddev->name, BUS_ID_SIZE);
return device_register(&ldddev->dev);
}
EXPORT_SYMBOL(register_ldd_device);
这里, 我们简单地填充一些嵌入的设备结构成员( 单个驱动不应当需要知道这个 ), 并且
注册这个设备到驱动核心. 如果我们想添加总线特定的属性到设备, 我们可在这里做.
为显示这个接口如何使用, 我们介绍另一个例子驱动, 我们称为 sculld. 它是在第 8 章
介绍的 scullp 驱动上的另一个变体. 它实现通用的内存区设备, 但是 sculld 也使用
Linux 设备模型, 通过 lddbus 接口.
sculld 驱动添加一个它自己的属性到它的设备入口; 这个属性, 称为 dev, 仅仅包含关
联的设备号. 这个属性可被一个模块用来加载脚本或者热插拔子系统, 来自动创建设备节
点, 当设备被添加到系统时. 这个属性的设置遵循常用模式:
s tatic ssize_t sculld_show_dev(struct device *ddev, char *buf)
{
struct sculld_dev *dev = ddev->driver_data;
return print_dev_t(buf, dev->cdev.dev);
}

static DEVICE_ATTR(dev, S_IRUGO, sculld_show_dev, NULL);
接着, 在初始化时间, 设备被注册, 并且 dev 属性被创建通过下面的函数:
static void sculld_register_dev(struct sculld_dev *dev, int index)
{
sprintf(dev->devname, "sculld%d", index);
dev->ldev.name = dev->devname;
dev->ldev.driver = &sculld_driver;
dev->ldev.dev.driver_data = dev;
register_ldd_device(&dev->ldev);
device_create_file(&dev->ldev.dev, &dev_attr_dev);
}
注意, 我们使用 driver_data 成员来存储指向我们自己的内部的设备结构的指针.

相关文章:

linux 设备模型之设备

在最低层, Linux 系统中的每个设备由一个 struct device 代表: struct device { struct device *parent; struct kobject kobj; char bus_id[BUS_ID_SIZE]; struct bus_type *bus; struct device_driver *driver; void *driver_data; void (*release)(struct device *dev); /* …...

电源滤波可采用 RC、LC、π 型滤波。电源滤波建议优选磁珠,然后才是电感。同时电阻、电感和磁珠必须考虑其电阻产生的压降。

电源滤波是为了减少电源中的噪声和干扰,确保电子设备正常工作。RC、LC、π 型滤波是常用的电源滤波器结构,其选择主要取决于需要滤波的频率范围和所需的滤波效果。 RC滤波器是由电阻和电容组成,适用于高频噪声的滤波。当电流通过电容时,电容会阻止高频噪声信号的通过,起到…...

STM32通用定时器-输入捕获-脉冲计数

一、知识点 编码器   两相编码器&#xff08;正交编码器&#xff09;&#xff1a;两相编码器由 A 相和 B 相组成&#xff0c;相位差为 90 度。当旋转方向为顺时针时&#xff0c;A 相先变化&#xff0c;然后 B 相变化&#xff1b;当旋转方向为逆时针时&#xff0c;B 相先变化…...

Flutter GetX 之 路由管理

路由管理是插件GetX常用功能之一&#xff0c;为什么说之一呢&#xff1f;因为GetX的功能远不止路由管理这么简单。 GetX的重要功能如下&#xff1a; 1、路由管理2、状态管理3、国际化4、主题5、GetUtil工具6、dialog 弹框7、snackbar 其实上面功能介绍的还是不够详细&#xff…...

基于单片机的农田灌溉系统(论文+源码)

1.系统设计 本系统主要实现如下目标&#xff1a; 1&#xff0e;可以实时监测土壤湿度&#xff1b; 2&#xff0e;土壤湿度太低时&#xff0c;进行浇水操作&#xff1b; 3&#xff0e;可以按键设置湿度的触发阈值&#xff1b; 4. 可以实现远程操控 5&#xff0e;可以实现手…...

分布式缓存 -- 基础

负载均衡 Ribbon 服务间通信的负载均衡工具&#xff0c;提供完善的超时重试机制 客户端的负载均衡器&#xff1a;在客户端将各个服务的信息拿到&#xff0c;在客户端本地做到请求的均衡分配 Ribbon 提供 LoadBalanced 注解&#xff0c;外搭配RestTemplate来做客户端的负载均衡…...

云计算复习笔记--期末

1、云计算的定义和本质&#xff1a; 云计算是一种按使用量付费的模式。云计算是分布式计算的一种。通过计算机网络&#xff08;多指因特网&#xff09;形成的计算能力极强的系统&#xff0c;可存储、集合相关资源并可按需配置&#xff0c;向用户提供个性化服务。 2、云计算服…...

【WPF.NET开发】WPF中的焦点

本文内容 键盘焦点逻辑焦点键盘导航以编程方式导航焦点焦点事件 在 WPF 中&#xff0c;有两个与焦点有关的主要概念&#xff1a;键盘焦点和逻辑焦点。 键盘焦点指接收键盘输入的元素&#xff0c;而逻辑焦点指焦点范围中具有焦点的元素。 本概述详细介绍了这些概念。 对于创建…...

【计算机设计大赛作品】豆瓣电影数据挖掘可视化—信息可视化赛道获奖项目深入剖析【可视化项目案例-22】

文章目录 一.【计算机设计大赛作品】豆瓣电影数据挖掘可视化—信息可视化赛道获奖项目深入剖析【可视化项目案例-22】1.1 项目主题:豆瓣电影二.代码剖析2.1 项目效果展示2.2 服务端代码剖析2.3 数据分析2.4 数据评分三.寄语四.本案例完整源码下载一.【计算机设计大赛作品】豆瓣…...

VS2019启动编辑并继续不起作用(.NET)

直接上方案 1)请确保您取消选中工具>选项>调试>常规下的选项&#xff1a;使用托管兼容模式和要求源文件与原始版本完全匹配。如下图&#xff1a; 2)请先取消选中编辑并继续选项&#xff0c;然后关闭您的旧解决方案&#xff0c;删除解决方案文件夹中的.vs隐藏文件夹&a…...

FFmpeg处理音视频的常用API及一般流程

FFmpeg是一个开源的音视频处理库&#xff0c;提供了丰富的API用于音视频的编解码、转码、过滤、播放等操作。 一、使用FFmpeg API解码涉及到的函数及一般流程如下&#xff1a; 1. av_register_all(): 注册所有的编解码器和格式。 av_register_all(); 2. avformat_open_inpu…...

Kotlin协程学习之-01

由于协程需要支持挂起、恢复、因此对于挂起点的状态保存就显得机器关键。类似的&#xff0c;线程会因为CPU调度权的切换而被中断&#xff0c;它的中断状态会保存在调用栈当中&#xff0c;因而协程的实现也按照是否开辟相应的调用栈存在以下两种类型&#xff1a; 有栈协程&…...

214.【2023年华为OD机试真题(C卷)】测试用例执行计划(排序题-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-测试用例执行计划二.解题思路三.题解代码Pytho…...

数一下 1到 100 的所有整数中出现多少个数字9并输出这些数字

分析&#xff1a; 我们知道 1-100的整数 i 中&#xff0c;9会出现在十位和个位上&#xff0c;数9出现的次数可以通过以下来实现&#xff1a; 个位是9 // i % 10得到整数 i 个位上的数十位是9 // i / 10得到整数 i 除了个位数的数字 这也是做这道题之后&#xff0c;我们需要…...

07. HTTP接口请求重试怎么处理?

目录 1、前言 2、实现方式 2.1、循环重试 2.2、递归重试 2.3、Spring Retry 2.4、Resilience4j 2.5、http请求网络工具内置重试方式 2.6、自定义重试工具 2.7、并发框架异步重试 2.8、消息队列 3、小结 1、前言 HTTP接口请求重试是指在请求失败时&#xff0c;再次发…...

分割数组的最大差值 - 华为OD统一考试

分割数组的最大差值 - 华为OD统一考试 OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 给定一个由若干整数组成的数组nums ,可以在数组内的任意位置进行分割,将该数组分割成两个非空子数组(即左数组和右数组),分别对子数组求和得到两个值.计算这两个值的差值…...

基于 Python+Django 技术栈,我开发了一款视频管理系统

学习过程中&#xff0c;遇到问题可以咨询作者 大家好&#xff0c;作为一名开发人员&#xff0c;平时比较愿意动手尝试各种有意思工具&#xff0c;因为笔者非常喜欢观看视频&#xff0c;尤其是YouTube、bilibili都是笔者非常喜欢的视频网站&#xff0c;所以想自己实现一个视频点…...

Python从入门到网络爬虫(内置函数详解)

前言 Python 内置了许多的函数和类型&#xff0c;比如print()&#xff0c;input()等&#xff0c;我们可以直接在程序中使用它们&#xff0c;非常方便&#xff0c;并且它们是Python解释器的底层实现的&#xff0c;所以效率是比一般的自定义函数更有效率。目前共有71个内置函数&…...

Python新年烟花代码

Pygame 绘制烟花的基本原理 1&#xff0c;发射阶段&#xff1a;在这一阶段烟花的形状是线性向上&#xff0c;通过设定一组大小不同、颜色不同的点来模拟“向上发射” 的运动运动&#xff0c;运动过程中 5个点被赋予不同大小的加速度&#xff0c;随着时间推移&#xff0c;后面的…...

oracle语法学习

oracle语法学习 1.备份表 create table bd_psndoc_temp as select * from bd_psndoc2.还原表 drop table bd_psndoc; create table bd_psndoc as select * from bd_psndoc_temp3.查询表的前5条记录 select * from bd_psndoc_temp where rownum<54.从一个表中复制所有的列…...

网络安全常见漏洞类型总结

网络安全常见漏洞类型总结 1、弱口令 原因&#xff1a; 与个人习惯和安全意识相关&#xff0c;为了避免忘记密码&#xff0c;使用一个非常容易记住的密码&#xff0c;或者是直接采用系统的默认密码等。 危害&#xff1a; 通过弱口令&#xff0c;攻击者可以进入后台修改资料&a…...

C++自制小游戏《屠夫躲猫猫》

大家好&#xff0c;我是派蒙&#xff0c;我写了一个《屠夫躲猫猫》的游戏&#xff0c;下面是源代码&#xff1a; #include <stdio.h> #include <conio.h> #include<bits/stdc.h> #include<windows.h> using namespace std; string ID[1001]; string N…...

LabVIEW在高级结构监测中的创新应用

LabVIEW在高级结构监测中的创新应用 LabVIEW作为一个强大的系统设计平台&#xff0c;其在基于BOTDA&#xff08;光时域反射分析&#xff09;技术的结构监测中发挥着核心作用。利用LabVIEW的高效数据处理能力和友好的用户界面&#xff0c;开发了一个先进的监测系统。该系统专门…...

关于GitHub的git推送命令时报错密码授权失败问题

参考文章&#xff1a;https://cloud.tencent.com/developer/article/2362326?areaId106001 问题描述 当新建GitHub仓库后&#xff0c;通过git clone xxxx&#xff0c;命令克隆仓库到本地&#xff0c;想要提交修改内容&#xff0c;此时会报错443链接远程仓库失败&#xff0c;解…...

WPF Blend for visual studio使用

Blend for visual studio介绍 VS自带的Blend for visual studio是专门用来做WPF、Metro等的界面设计的可视化工具&#xff0c;其功能和PS类似。其目的让做界面和后台的程序分开&#xff0c;能快速绘制形状和路径、修改对象样式、动态显示对象(动画)、显示数据等高级操作。VS与B…...

云卷云舒:【实战篇】Redis迁移

1. 简介 Remote Dictionary Server(Redis)是一个由Salvatore Sanfilippo写的key-value存储系统&#xff0c;是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。 2. 迁移原理 redis-sh…...

[C#]yolov8-onnx在winform部署手势识别模型

【官方框架地址】 https://github.com/ultralytics/ultralytics.git 【算法介绍】 YOLOv8 是一个 SOTA 模型&#xff0c;它建立在以前 YOLO 版本的成功基础上&#xff0c;并引入了新的功能和改进&#xff0c;以进一步提升性能和灵活性。具体创新包括一个新的骨干网络、一个新…...

【uniapp】 uniapp 修改tabBar图标大小和navigationBar字体大小

app.vue文件中修改 //导航栏字体 .uni-page-head .uni-page-head__title{font-size: 30rpx !important; } // tab图标 .uni-tabbar .uni-tabbar__icon {width: 25rpx !important;height: 25rpx !important; }大佬地址&#xff1a;https://blog.csdn.net/AAAXiaoApple/article/…...

Visual Studio 2017 + opencv4.6 + contribute + Cmake(Aruco配置版本)指南

之前配置过一次这个&#xff0c;想起这玩意就难受&#xff0c;贼难配置。由于要用到里面的一个库&#xff0c;不得已再进行配置。看网上的博客是真的难受&#xff0c;这写一块&#xff0c;那里写一块&#xff0c;乱七八糟&#xff0c;配置一顿发现写的都是错的&#xff0c;还得…...

自定义事件总线

文章目录 什么是自定义事件总线具体实现思路分析定义结构实现 on实现 emit实现 off 源码 什么是自定义事件总线 自定义事件总线属于一种观察着模式&#xff0c;其中包括三个角色发布者&#xff08;Publisher&#xff09;&#xff1a;发出事件&#xff08;Event&#xff09;订阅…...

怎么做直播网站/外贸seo

MongoDB分片集群的搭建分片的概念分片集群的优势分片集群包含的组件部署MongoDB分片集群的准备工作配置shard配置Config Server配置 mongos配置复制集进入节点服务器集群配置节点衔接启动mongos指定分片键对集合分片分片的概念 分片&#xff08;sharding)是一种跨多台机器分布数…...

淄川政府网站建设托管/引流人脉推广软件

Semaphore&#xff1a;其实.NET中的信号量&#xff08;Semaphore&#xff09;是操作系统维持的一个整数。当整数位0时。其他线程无法进入。当整数大于0时&#xff0c;线程可以进入。每当一个线程进入&#xff0c;整数-1&#xff0c;线程退出后整数1。整数不能超过信号量的最大请…...

学校文化建设的网站/网络营销战略

2019独角兽企业重金招聘Python工程师标准>>> 性能与可伸缩性 性能包括&#xff1a;服务时间、延迟时间、吞吐率、效率、容量等 可伸缩性&#xff1a;当增加计算资源时&#xff08;例如CPU、内存、存储容量或I/O带宽&#xff09;&#xff0c;程序的吞吐量或者处理能力…...

完美政府网站(cms)管理系统/推广软文300字

测试准备过程 1,设置环境变量&#xff0c;导入测试数据&#xff0c;具体方法见上文 su - Oracle exportPATH/monitor/agent_12c/core/12.1.0.1.0/jdk测试准备过程1,设置环境变量&#xff0c;导入测试数据&#xff0c;具体方法见上文su - OracleexportPATH/monitor/agent_12c/co…...

岳阳网站建设推广/免费做网站的平台

1.前向传播 引用一个网站的图&#xff1a; 具体来说&#xff0c;就是2行代码&#xff0c;图片中的f为激活函数&#xff0c;这里用sigmoid作为激活函数&#xff0c;事实上有很多其它的套路&#xff0c;这里只讲神经网络的数学原理及初级使用&#xff0c;不会做任何深入扩展&…...

林芝做网站/做seo网页价格

今天测试一款Chrome插件&#xff0c;这款插件提供了一些本地页面做测试用&#xff0c;在解决一些技术问题之后&#xff0c;在插件的官网上可以测试成功了&#xff0c;但是在本地页面上测试时Chrome始终会拦截插件&#xff0c;即使在右上角的地址栏中允许该本地页面始终使用插件…...