linux 设备模型之类

我们在本章中要考察最后的设备模型概念是类.一个类是一个设备的高级视图, 它抽象出
低级的实现细节. 驱动可以见到一个 SCSI 磁盘或者一个 ATA 磁盘, 在类的级别, 它们都
是磁盘. 类允许用户空间基于它们做什么来使用设备, 而不是它们如何被连接或者它们如
何工作.
几乎所有的类都在 sysfs 中在 /sys/class 下出现. 因此, 例如, 所有的网络接口可在
/sys/class/net 下发现, 不管接口类型. 输入设备可在 /sys/class/input 下, 以及串
行设备在 /sys/class/tty. 一个例外是块设备, 由于历史的原因在 /sys/block.

类成员关系常常由高级的代码处理, 不必要驱动的明确的支持. 当 sbull 驱动( 见 16
章) 创建一个虚拟磁盘设备, 它自动出现在 /sys/block. snull 网络驱动(见 17 章)没
有做任何特殊事情给它的接口在 /sys/class/net 中出现. 将有多次, 但是, 当驱动结束
直接处理类.
在许多情况, 类子系统是最好的输出信息到用户空间的方法. 当一个子系统创建一个类,
它完全拥有这个类, 因此没有必要担心哪个模块拥有那里发现的属性. 它也用极少的时间
徘徊于更加面向硬件的 sysfs 部分来了解, 它不是一个直接浏览的好地方. 用户会更加
高兴地在 /sys/class/some-widget 中发现信息, 而不是,
/sys/device/pci0000:00/0000:00:10.0/usb2/2-0:1.0.
驱动核心输出 2 个清晰的接口来管理类. class_simple 函数设计来尽可能容易地添加新
类到系统. 它们的主要目的, 常常, 是暴露包含设备号的属性来使能设备节点的自动创建.
常用的类接口更加复杂但是同时提供更多特性. 我们从简单版本开始.

class_simple 接口

class_simple 接口意图是易于使用, 以至于没人会抱怨没有暴露至少一个包含设备的被
分配的号的属性. 使用这个接口只不过是一对函数调用, 没有通常的和 Linux 设备模型
关联的样板.
第一步是创建类自身. 使用一个对 class_simple_create 的调用来完成:
struct class_simple *class_simple_create(struct module *owner, char *name);
这个函数使用给定的名子创建一个类. 这个操作可能失败, 当然, 因此在继续之前返回值
应当一直被检查( 使用 IS_ERR, 在第 1 章的"指针和错误值"一节中描述过).
一个简单的类可被销毁, 使用:
void class_simple_destroy(struct class_simple *cs);
创建一个简单类的真实目的是添加设备给它; 这个任务使用:
struct class_device *class_simple_device_add(struct class_simple *cs, dev_t
devnum, struct device *device, const char *fmt, ...);
这里, cs 是之前创建的简单类, devnum 是分配的设备号, device 是代表这个设备的
struct device, 其他的参数是一个 printk-风格 的格式串和参数来创建设备名子. 这个
调用添加一项到类, 包含一个属性, dev, 含有设备号. 如果设备参数是非 NULL, 一个符
号连接( 称为 device )指向在 /sys/devices 下的设备的入口.
可能添加其他的属性到设备入口. 它只是使用 class_device_create_file, 我们在下一
节和完整类子系统所剩下的内容讨论.
当设备进出时类产生热插拔事件. 如果你的驱动需要添加变量到环境中给用户空间事件处
理者, 可以建立一个热插拔回调, 使用:

int class_simple_set_hotplug(struct class_simple *cs,
int (*hotplug)(struct class_device *dev,
char **envp, int num_envp,
char *buffer, int buffer_size));
当你的设备离开时, 类入口应当被去除, 使用:
void class_simple_device_remove(dev_t dev);
注意, 由 class_simple_device_add 返回的 class_device 结构这里不需要; 设备号(它
当然应当是唯一的)足够了.

完整的类接口

class_simple 接口满足许多需要, 但是有时需要更多灵活性. 下面的讨论描述如何使用
完整的类机制, class_simple 正是基于此. 它是简短的: 类函数和结构遵循设备模型其
他部分相同的模式, 因此这里没有什么真正是新的.

管理类

一个类由一个 struct class 的实例来定义:
struct class {
char *name;
struct class_attribute *class_attrs;
struct class_device_attribute *class_dev_attrs;
int (*hotplug)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
void (*release)(struct class_device *dev);
void (*class_release)(struct class *class);
/* Some fields omitted */
};
每个类需要一个唯一的名子, 它是这个类如何在 /sys/class 中出现. 当这个类被注册,
由 class_attrs 所指向的数组中列出的所有属性被创建. 还有一套缺省属性给每个添加
到类中的设备; class_dev_attrs 指向它们. 有通常的热插拔函数来添加变量到环境中,
当事件产生时. 还有 2 个释放方法: release 在无论何时从类中去除一个设备时被调用,
而 class_release 在类自己被释放时调用.
注册函数是:
int class_register(struct class *cls);
void class_unregister(struct class *cls);
使用属性的接口不应当在这点吓人:
struct class_attribute {
struct attribute attr;

ssize_t (*show)(struct class *cls, char *buf);
ssize_t (*store)(struct class *cls, const char *buf, size_t count);
};
CLASS_ATTR(name, mode, show, store);
int class_create_file(struct class *cls, const struct class_attribute *attr);
void class_remove_file(struct class *cls, const struct class_attribute *attr);

类设备

一个类的真正目的是作为一个是该类成员的设备的容器. 一个成员由 struct
class_device 来表示:
struct class_device {
struct kobject kobj;
struct class *class;
struct device *dev;
void *class_data;
char class_id[BUS_ID_SIZE];
};
class_id 成员持有设备名子, 如同它在 sysfs 中的一样. class 指针应当指向持有这个
设备的类, 并且 dev 应当指向关联的设备结构. 设置 dev 是可选的; 如果它是非 NULL,
它用来创建一个符号连接从类入口到对应的在 /sys/devices 下的入口, 使得易于在用户
空间找到设备入口. 类可以使用 class_data 来持有一个私有指针.
通常的注册函数已经被提供:
int class_device_register(struct class_device *cd);
void class_device_unregister(struct class_device *cd);
类设备接口也允许重命名一个已经注册的入口:
int class_device_rename(struct class_device *cd, char *new_name);
类设备入口有属性:
struct class_device_attribute {
struct attribute attr;
ssize_t (*show)(struct class_device *cls, char *buf);
ssize_t (*store)(struct class_device *cls, const char *buf,
size_t count);
};
CLASS_DEVICE_ATTR(name, mode, show, store);
int class_device_create_file(struct class_device *cls, const struct class_device_attribute
*attr);
void class_device_remove_file(struct class_device *cls, const struct
class_device_attribute *attr);

一个缺省的属性集合, 在类的 class_dev_attrs 成员, 被创建当类设备被注册时;
class_device_create_file 可用来创建额外的属性. 属性还可以被加入到由
class_simple 接口创建的类设备.

类接口

类子系统有一个额外的在 Linux 设备模型其他部分找不到的概念. 这个机制称为一个接
口, 但是它是, 也许, 最好作为一种触发机制可用来在设备进入或离开类时得到通知.
一个接口被表示, 使用:
struct class_interface {
struct class *class;
int (*add) (struct class_device *cd);
void (*remove) (struct class_device *cd);
};
接口可被注册或注销, 使用:
int class_interface_register(struct class_interface *intf);
void class_interface_unregister(struct class_interface *intf);
一个接口的功能是简单明了的. 无论何时一个类设备被加入到在 class_interface 结构
中指定的类时, 接口的 add 函数被调用. 这个函数可进行任何额外的这个设备需要的设
置; 这个设置常常采取增加更多属性的形式, 但是其他的应用都可能. 当设备被从类中去
除, remove 方法被调用来进行任何需要的清理.
可注册多个接口给一个类.

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

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

相关文章

操作系统实验二

实验二 观察Linux行为,使用proc文件系统 一、实验目的 学习Linux内核、进程、存储和其他资源的一些重要特征。读/proc/stat文件,计算并显示系统CPU占用率和用户态CPU占用率。(编写一个程序使用/proc机制获得以及修改机器的各种资源参数。需要…

优化改进YOLOv5算法之AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv

1 AKConv原理 AKConv: Convolutional Kernel with Arbitrary Sampled Shapes andArbitrary Number of Parameters 摘要:基于卷积运算的神经网络在深度学习领域取得了令人瞩目的成果,但标准卷积运算存在两个固有的缺陷。一方面,卷积运算仅限于局部窗口,无法捕获其他位置的…

安卓上使用免费的地图OpenStreetMap

前一段使用了微信的地图,非常的好用。但是存在的问题是海外无法使用,出国就不能用了; 其实国内三家:百度,高德,微信都是一样的问题,当涉及到商业使用的时候需要付费; 国外除了谷歌…

51单片机介绍

1 单片机简介 单片机,英文Micro Controller Unit,简称MCU 内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能 单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设…

【Leetcode】227.基本计算器II

一、题目 1、题目描述 给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。 整数除法仅保留整数部分。 你可以假设给定的表达式总是有效的。所有中间结果将在 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31} - 1] [−2

2.6 KERNEL LAUNCH

图2.15在vecAdd函数中显示最终主机代码。此源代码完成了图2.6.中的骨架。2.12和2.15共同说明了一个简单的CUDA程序,该程序由主机代码和设备内核组成。该代码是硬接的,每个线程块使用256个线程。然而,使用的线程块的数量取决于向量&#xff08…

jenkins通过流水线自动部署项目(k8s部署)

参考:https://www.cnblogs.com/rb2010/p/16195443.html docker 拉取镜像到本地: docker pull docker.io/jenkins/jenkins:2.164配置卷挂载:使用nfs 参考:https://www.kuboard.cn/learning/k8s-intermediate/persistent/nfs.htm…

RT-DETR改进Shape-IoU损失函数:考虑边界框形状和比例的更准确的指标

💡本篇内容:RT-DETR改进Shape-IoU损失函数:考虑边界框形状和比例的更准确的指标 💡🚀🚀🚀本博客 改进源代码改进 适用于 RT-DETR 按步骤操作运行改进后的代码即可 💡参考论文地址:https://arxiv.org/abs/2312.17663 2023年12月最新发表论文:IoU最新的损失函数…

指针传参误区

C语言中指针作为形参传递时,func(*a, *b) 这种形式的话,是无法通过简单的 ab来修改的,在函数体内a的地址确实被修改成b的地址了,但是当函数执行结束时,a的地址会重新回到原本的地址里面&#xf…

卷积神经网络|猫狗分类系列--导入kaggle猫狗数据集

解决任何真实问题的重要一步是获取数据,Kaggle提供了大量不同数据科学问题的竞赛。 我们将从 https://www.kaggle.com/competitions/dogs-vs-cats/data 下载猫狗数据集,并对其进行一定的操作,以正确的导入到我们的计算机,为接下…

四 视图

1、实验目的 理解SQL成熟设计基本规范,能够熟练使用SQL语句来创建需要的视图,定义数据库外模式,并能使用所创建的视图实现数据管理。 2、实验内容及要求 使用SQL对数据库进行各类查询数据操纵操作,掌握单行数据插入、多行数据插…

设计模式的艺术P1基础—第1章 概述

刘伟,2020 概述:4部分,26章。 P1:基础(1-2章) P2:创建型设计模式(创建艺术,3-8章) P3:结构型设计模式(组合艺术,9-15章) P4:行为型设计模式&…

【设计模式】 模板方法模式

前言 1. 单例模式(Singleton Pattern):保证一个类只有一个实例,并提供一个全局的访问点。 2. 工厂模式(Factory Pattern):定义一个创建对象的接口,但由子类决定要实例化的类是哪一…

2_工厂设计_工厂方法和抽象工厂

工厂设计模式-工厂方法 1.概念 工厂方法模式(Fatory Method Pattern ) 是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。 在工厂方法模式中用户只需要关心所需产品对应的工厂,…

css——box-shadow阴影效果

/* box-shadow:内外阴影(inset:内阴影,水平阴影,垂直阴影,阴影模糊距离,阴影大小,阴影颜色) */box-shadow: 0 0 50px #ccc; 引用来源:box-shadow详解_box-shadow属性详解-CSDN博客

AUTOSAR开发文档

目录 目录 状态机电源管理开发... I 文档... I 1. 综述... 1 2. 系统硬件架构图... 1 3. 状态机设计方案... 2 4. 电源管理方案... 4 综述 本文档主要描述了MCU芯片TC297的AUTOSAR方案。MCU的基础软件由AUTOSAR软件实现&#xff0…

嵌入式——循环队列

循环队列 (Circular Queue) 是一种数据结构(或称环形队列、圆形队列)。它类似于普通队列,但是在循环队列中,当队列尾部到达数组的末尾时,它会从数组的开头重新开始。这种数据结构通常用于需要固定大小的队列,例如计算机内存中的缓冲区。循环队列可以通过数组或链表实现,…

微信小程序实战-01翻页时钟-1

文章目录 前言需求分析功能设计界面设计界面结构设计界面样式设计 逻辑设计 单页功能实现运行结果 前言 我经常在手机上用的一款app有一个功能是翻页时钟,基于之前学习的小程序相关的基础内容,我打算在微信小程序中也设计一个翻页时钟功能,J…

大模型实战营Day2 作业

基础作业 1 使用 InternLM-Chat-7B 模型生成 300 字的小故事 2 熟悉 hugging face 下载功能,使用 huggingface_hub python 包,下载 InternLM-20B 的 config.json 文件到本地 进阶作业 1 完成浦语灵笔的图文理解及创作部署 2 完成 Lagent 工具调用 Demo…

大数据计算基础真题回忆

转载学长20 21的真题 转载链接 注:每年的课件可能会有更改,内容不一样,所以读者复习的时候以所在年份的课件为准 2020 ​ 2021 笔者2023秋 2023 都是大题,没有选择题。 改进的近似算法中,结合具体的例子说明&am…