0

Linux 设备模型之 Uevent

 1 year ago
source link: https://www.jianshu.com/p/10653d83909d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Linux 设备模型之 Uevent

0.3262019.04.02 14:39:02字数 1,453阅读 5,829

此文始于 2019-04-02,这是在简书的第一篇文章,目的是为了练习 markdown语法。先选择一篇文章进行 copy to write,结合目前正在看的内容 android ueventd,选一篇对 uevent 的描述来进行练习。

Linux 设备模型之 Uevent

1. Uevent的功能

uevent 是 Kobject 的一部分,用于在 Kobject 状态发生改变时,例如增加、移除等,通知用户空间程序,用户空间程序接收到这样的时间后,会做出相应的处理。该机制通常是用来支持热插拔设备的,例如U盘插入后,USB相关 的驱动软件会动态创建用于表示该 U盘的 device 结构(相应的也包括其中的 kobject),并告知用户空间程序,为该 U盘动态的创建/dev/目录下的设备节点,更进一步,可以通知其他应用程序,将该 U盘 mount 到系统中,从而动态的支持该设备。

2. sysfs 概述

设备节点是为设备驱动所创建的,而设备device和驱动driver都是以链表的形式连接在总线bus上的,而设备——驱动——总线的更上一层就是sysfs层。
sysfs是一个内存文件系统,它把连接在系统上的设备和总线组织成为一个分级的文件,用户空间的程序同样可以利用这些信息,以实现和内核的交互。sysfs文件系统是当前系统上实际设备树的一个直观反映,用mount命令查看可以得知其挂载在“/sys”下 sysfs on /sys type sysfs (rw,seclabel,relatime))。当一个kobject被创建的时候,对应的sys文件和目录也就被创建了;其主要文件目录如下:

  • /sys/block 存放块设备,提供以设备名(如sda)到/sys/devices的符号链接
  • /sys/bus 按总线类型分类,在某个总线目录之下可以找到连接该总线的设备的符号链接,指向/sys/devices。某个总线目录之下的 drivers 目录包含了该总线所需的所有驱动的符号链接对应kernel中的 struct bus_type
  • /sys/class 按设备功能分类,如输入设备在 /sys/class/input 之下,图形设备在 /sys/class/graphics 之下,是指向 /sys/devices 目录下对应设备的符号链接对应kernel中的 struct class
  • /sys/dev 按设备驱动程序分层(字符设备/块设备),提供以major:minor为名到 /sys/devices 的符号链接对应kernel中的 struct device_driver
  • /sys/devices 包含所有被发现的注册在各种总线上的各种物理设备。
    所有的物理设备都按其在总线上的拓扑结构来显示,除了 platform devices 和 system devices 。platform devices一般是挂在芯片内部高速或者低速总线上的各种控制器和外设,能被CPU直接寻址。system devices不是外设,他是芯片内部的核心结构,比如CPU,timer等,他们一般没有相关的driver,但是会有一些体系结构相关的代码来配置他们对应kernel中的 struct device
    上面展现了在sys目录下总线,设备,驱动和类所对应的文件,而他们的区别为:
  • device用于描述各种设备,其保存了所有的设备信息
  • driver 用于驱动 device ,其保存了所有能够被它所驱动的设备链表。
  • bus 是连接 CPU 和 device 的桥梁,其保存了所有挂载在它上面的设备链表和驱动这些设备的驱动链表。
  • class 用于描述一类 device ,其保存了所有该类 device 的设备链表。

创建设备节点文件的过程

下图描述了设备节点文件的创建过程:

10653d83909d
创建设备节点文件的整个过程

由此可知,设备模型中任何设备有事件需要上报时,会触发 uevent提供的接口,uevent模块准备好上报事件的格式后,可以通过两个途径上报到用户空间:

  • 通过 kmod 模块,直接调动用户空间的可执行文件
  • 通过 netlink 通信机制,将事件从内核空间传递给用户空间
    PS: 目前多采用 netlink 通信机制,ueventd 也是采用 netlink机制创建 socket 与 kernel 进行通信。
    netlink基本概念
    用户空间程序接收到上报的uevent之后就可以根据其event类型进行相应操作了。

uevent的数据结构描述

kobject.h定义了uevent相关的常量和数据结构,如下:

kernel/lib/kobject_uevent.c  
/* the strings here must match the enum in include/linux/kobject.h */  
static const char *kobject_actions[] = {  
    [KOBJ_ADD] =        "add",  
    [KOBJ_REMOVE] =     "remove",  
    [KOBJ_CHANGE] =     "change",  
    [KOBJ_MOVE] =       "move", //暂未看到ueventd有具体处理  
    [KOBJ_ONLINE] =     "online",  
    [KOBJ_OFFLINE] =    "offline",//暂未看到ueventd有具体处理  
};  
/* 
 * The actions here must match the index to the string array 
 * in lib/kobject_uevent.c 
 * 
 * Do not add new actions here without checking with the driver-core 
 * maintainers. Action strings are not meant to express subsystem 
 * or device specific properties. In most cases you want to send a 
 * kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event 
 * specific variables added to the event environment. 
 */  
kernel/include/linux/kobject.h  
 enum kobject_action {     
     KOBJ_ADD,
     KOBJ_REMOVE,      
     KOBJ_CHANGE, 
     KOBJ_MOVE,  
     KOBJ_ONLINE, 
     KOBJ_OFFLINE,  
     KOBJ_MAX   
 };  

kobject_action定义了event的类型,包括:

  • ADD/REMOVE,Kobject(或上层数据结构)的添加/移除事件。
  • ONLINE/OFFLINE,Kobject(或上层数据结构)的上线/下线事件,其实是是否使能。
  • CHANGE,Kobject(或上层数据结构)的状态或者内容发生改变。
  • MOVE,Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构)。
  • CHANGE,如果设备驱动需要上报的事件不再上面事件的范围内,或者是自定义的事件,可以使用该event,并携带相应的参数。

以上就是 uevent 的基础知识,作为了解 ueventd 前的准备。

在后续日子可以完全使用 markdown 语言誊写文档

参考的文章

Linux设备模型之 Uevent


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK