内核笔记](九)——sysfs相关API

简介: 内核笔记](九)——sysfs相关API

一、什么是sysfs?


Sysfs 是Linux 2.6所提供的一种虚拟文件系统。这个文件系统不仅可以把设备(devices)和驱动程序(drivers)的信息从内核输出到用户空间,也可以用来对设备和驱动程序做设置。

简单的说,sysfs是一个基于内存的文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用。


sysfs 给应用程序提供了统一访问设备的接口,但可以看到, sysfs 仅仅是提供了一个可以统一访问设备的框架,但究竟是否支持 sysfs 还需要各设备驱动程序的编程支持;在 2.6 内核 诞 生 5年以来的发展中,很多子系统、设备驱动程序逐渐转向了 sysfs 作为与用户空间友好的接口,但仍然也存在大量的代码还在使用旧的 proc 或虚拟字符设备的 ioctl 方式;如果仅从最终用户的角度来说, sysfs 与 proc 都是在提供相同或类似的功能,对于旧的 proc 代码,没有绝对的必要去做 proc 至 sysfs 的升级;


二、注册流程


/sys/bus:该目录包含linux下的总线设备,每个子目录下主要包含两个目录:device和driver.


Linux 设备总线驱动模型


0a2653c851af460fa595bd959398a8f1.png


简单来说,bus 负责维护 注册进来的devcie 与 driver ,每注册进来一个device 或者 driver 都会调用 Bus->match 函数 将device 与 driver 进行配对,并将它们加入链表,如果配对成功,调用Bus->probe或者driver->probe函数, 调用 kobject_uevent 函数设置环境变量,mdev进行创建设备节点等操作。后面,我们从 Bus driver 到 device三个部分进行详细的分析。

0eacb84100b54626af849e6b562bf92a.png

这张图也可以直观看出,系统启动到再到驱动的注册,也很直观


三、bus_register


kzalloc ----> subsys. private空间

kobjetset name ----> 设置bus名到kobjet

kset register ----> 在/5y/bus下创建kobjet目录及ttribute文件

bus_ create. file ----> 创建ueven文件

kset reate. and add ----> 创建5y/s/ox/device8录

kset _create and add ----> 创建5/s/0o/driver目录

add probe files ----> 创建drivers. probe及drivers _autoprobe文件

bus. add groups ----> 创建bus->bus. group属性文件

那么bus_register 函数处理的工作有哪些呢,博主在网上找了一下解释,写的挺好,如下:


1、将 Bus 与 priv 相互建立联系

2、BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

3、设置 bus->priv->subsys(kset).kobj 的名字为 bus->name

4、设置 bus->priv->subsys(kset).kobj.kset 指向 bus_kset

5、设置 bus->priv->subsys(kset).kobj.ktype 为 bus_ktype ,提供 show store 函数

6、设置 bus->priv->drivers_autoprobe = 1;

7、注册 bus->priv->subsys(kset) 对应于图中④与⑥的关系

由于4,且没有指定bus->priv->subsys(kset).kobj.Parent,会将 bus_kest.kobj 设置为 bus->priv->subsys(kset).kobj.Parent 因此,会将bus->priv->subsys(kset).kobj.entry 加入 bus_kest 链表,且会在/sys/bus目录下创建相应的总线目录/sys/bus/ ( b u s − > n a m e ) ,例如 / s y s / b u s / p l a t f o r m 8 、创建 b u s a t t r u e v e n t − > a t t r 属性文件 9 、创建并注册 d e v i c e s k s e t , d e v i c e s k s e t . k o b j . p a r e n t = b u s − > p r i v − > s u b s y s . k o b j , 名字为 d e v i c e ,因此会创建 / s y s / b u s / (bus->name),例如 /sys/bus/platform 8、创建 bus_attr_uevent->attr 属性文件 9、创建并注册 devices_kset ,devices_kset.kobj.parent = bus->priv->subsys.kobj ,名字为 device ,因此会创建 /sys/bus/ (bus−>name),例如/sys/bus/platform8、创建bus

a


ttr

u


event−>attr属性文件9、创建并注册devices

k


set,devices

k


set.kobj.parent=bus−>priv−>subsys.kobj,名字为device,因此会创建/sys/bus/(bus->name)/devices

10、创建并注册 drivers_kset ,drivers_kset.kobj.parent = bus->priv->subsys.kobj ,名字为 drivers ,因此会创建 /sys/bus/$(bus->name)/drivers

11、初始化 bus->priv->klist_devices 链表

12、初始化 bus->priv->klist_drivers 链表

13、创建 bus->bus_attrs 属性文件


原码如下


int bus_register(struct bus_type *bus)
{
  int retval;
  struct bus_type_private *priv;
  priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
/* 1. bus 与 prv 相互建立联系 */
  // 私有数据 .bus ->  bus 本身
  priv->bus = bus;
  // bus->p 指向 priv
  bus->p = priv;
  // 内核通知链
  BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
/* 设置 bus->prv->subsys->kobj */
  // 设置 priv->subsys.kobj.name = bus->name  对应于/sys/ 目录下的目录名
  retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
  // 所有的 priv->subsys.kobj.kset 指向 bus_kse 对应于图中④与六的关系
  priv->subsys.kobj.kset = bus_kset;
  // 所有的priv->subsys.kobj.ktype 等于 bus_ktype
  priv->subsys.kobj.ktype = &bus_ktype;
  priv->drivers_autoprobe = 1;
/* 注册 kset (bus->prv->subsys priv->devices_kset priv->drivers_kset) */  
  // 注册 priv->subsys ,由于 priv->subsys.kobj.kset = bus_kset,所以会在 /sys/bus/目录下创建 目录 如/sys/bus/plateform
  retval = kset_register(&priv->subsys);
  // sysfs_create_file(&bus->p->subsys.kobj, &bus_attr_uevent->attr);
  retval = bus_create_file(bus, &bus_attr_uevent);
  // 由于 priv->subsys.kobj.kset = bus_kset ,因此会创建 /sys/bus/XXX/devices 目录 如 /sys/bus/plateform/devices
  priv->devices_kset = kset_create_and_add("devices", NULL,
       &priv->subsys.kobj);
  // 同理 创建 /sys/bus/XXX/devices 目录 如 /sys/bus/plateform/drivers
  priv->drivers_kset = kset_create_and_add("drivers", NULL,
       &priv->subsys.kobj);
  // 初始化 klist_devices 并设置get put 函数  初始化 klist_drivers 不知为何没有get put ?
  klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
  klist_init(&priv->klist_drivers, NULL, NULL);
  retval = add_probe_files(bus);  // static inline int add_probe_files(struct bus_type *bus) { return 0; }
  // 添加 bus->attrs 属性文件
  retval = bus_add_attrs(bus);
  return 0;
}


四、注册以致用(probe)


通过上文的注册

0a2653c851af460fa595bd959398a8f1.png

通过这张图可以看出,驱动和设备需要进行match进行匹配,如果没有成功匹配到,则适用所有设备


相关文章
|
7月前
|
Java API
Java基础—笔记—API篇
这篇内容介绍了Java中的API相关知识,包括`Object`类作为所有类的父类,其核心方法`toString()`、`equals()`和`clone()`。`toString()`默认返回对象地址,重写后可返回内容;`equals()`默认比较地址,重写后比较内容。`clone()`用于对象克隆,提到了浅克隆与深克隆的概念。此外,还介绍了`Objects`工具类,它提供如`equals()`、`isNull()`和`nonNull()`等方法进行条件判断。
35 0
|
7月前
|
JSON API 数据格式
实时获取小红书笔记详情的API使用与解析
小红书是一个以分享消费经验、生活方式为主的社交平台,拥有大量的用户和内容。为了更好地了解用户在小红书上的行为和内容,许多开发者选择使用小红书开放平台提供的API接口。本文将介绍如何通过小红书笔记详情API实现实时数据获取,并给出相应的代码示例。
|
3月前
|
JSON API 开发者
小红书 API 接口使用指南:笔记详情数据接口的接入与使用
小红书是一款广受喜爱的生活方式分享社交平台,涵盖旅行、美食等领域。其API允许开发者批量获取笔记内容、图片链接及用户互动数据,助力内容分析与营销策略优化。要使用API,需先注册开发者账号并通过认证获取密钥;随后依据官方文档构建与发送HTTP请求,最后处理JSON格式响应数据。整个过程中,请务必遵循平台使用条款,尊重用户隐私权。
|
4月前
|
存储 Linux API
Linux源码阅读笔记08-进程调度API系统调用案例分析
Linux源码阅读笔记08-进程调度API系统调用案例分析
|
4月前
|
Linux API
Linux源码阅读笔记07-进程管理4大常用API函数
Linux源码阅读笔记07-进程管理4大常用API函数
|
4月前
|
JSON API 开发者
小红书 API 接口最新指南:笔记详情数据接口的接入与使用
小红书笔记详情数据接口由其开放平台提供,让开发者通过API批量获取笔记的全面信息,如标题、内容、图片及互动数据等。可用于数据分析、洞察用户行为与内容趋势,支持精准的内容创作与营销策略。使用前需注册认证并获取API密钥;依据官方文档构建与发送请求;处理JSON响应数据。注意遵守调用频率限制、保持数据更新及确保数据使用的合规性。
|
7月前
|
数据采集 API 开发者
调用API接口获取小红书笔记详情数据(小红书怎么推广)
小红书平台对于其API的使用有严格的规定和限制,并且并非所有的功能和数据都通过公开API提供。关于获取小红书笔记详情的API,以下是一些建议和指导:
|
7月前
|
数据采集 安全 API
如何实时获取小红书笔记详情的API使用与解析
小红书是一个以分享消费经验、生活方式为主的社交平台,拥有大量的用户和内容。为了更好地了解用户在小红书上的行为和内容,许多开发者选择使用小红书开放平台提供的API接口。本文将介绍如何通过小红书笔记详情API实现实时数据获取,并给出相应的代码示例。
|
7月前
|
Web App开发 Rust JavaScript
Rust 笔记:WebAssembly 的 JavaScript API
Rust 笔记:WebAssembly 的 JavaScript API
177 0
|
7月前
|
数据挖掘 API
解锁新视角:小红书笔记详情API的隐藏价值探索
在数字化时代,小红书笔记详情API为我们提供了一个全新的视角,帮助我们深入挖掘隐藏的价值。通过这个强大的工具,我们可以解锁新视角,发现潜在的市场机会和用户需求,从而创造更大的商业价值。