Linux 热插拔(Hot Plug)处理机制系列

2024-03-13 16:38

本文主要是介绍Linux 热插拔(Hot Plug)处理机制系列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

将可移动设备连入系统时,系统的后台中会依次发生如下事件:
内核检测到新硬件插入,然后分别通知 hotplug udev 。前者用来装入相应的内核模块 ( usb-storage) ,而后者用来在 /dev 中创建相应的设备节点 ( /dev/sda1)
udev 创建了相应的设备节点之后,会将这一消息通知 hal 的守护程序 (hald) 。当然 udev 还得保证新创建的设备节点可以被普通用户访问。
hotplug 装入了相应的内核模块之后,会把这一消息通知给 hald
hald 在受到 hotplug udev 发出的消息之后,认为新硬件已经正式被系统认可了。此时它会通过一系列精心编写的规则文件(就是传说中的 xxx-policy.fdi ),把发现新硬件的消息通过 dbus 发送出去,同时还会调用 update-fstab fstab-sync 来更新 /etc/fstab ,为相应的设备节点创建适合的挂载点。
卷管理器会监听 dbus 中发现新硬件的消息。根据所插入的硬件 ( 区分 U 盘和数码相机等 ) 不同,卷管理器会先将相应的设备节点挂载到 hald 创建的挂载点上,然后再打开不同的应用程序。

当然,如果是在 CDROM 中插入光盘,过程可能比较简单。因为 CDROM 本身就是一个固定的硬件,无需 hotplug udev 的协助:
hald 会自己监视 CDROM ,并且将光盘托架开合的消息通过 dbus 发出去。
卷管理器负责检查 CDROM 中的盘片内容,进行挂载,并调用合适的应用程序。

要注意,hald的工作是从上游得到硬件就绪的消息,然后将这个消息转发到dbus中。尽管它会调用程序来更新fstab,但实际上它自己并不执行挂载的工作。

下面是上面的过程中涉及的模块和工具:
hotplug

hotplug 包和内核里的hotplug模块不是一回事,2.6内核里的pci_hotplug.ko是一个内核模块,而hotplug包是用来处理内核产生的hotplug事件。这个软件包还在引导时检测现存的硬件并在运行的内核中加载相关模块。

不但有热插拔,还有冷插拔(cold pluging)。热插拔在内核启动之后发生,而“cold pluging”发生在内核启动的过程中。

/etc/hotplug/*.rc 这些脚本用于冷插拔(检测和激活在系统启动时已经存在的硬件)。它们被 hotplug 初始化脚本调用。*.rc 脚本会尝试恢复系统引导时丢失的热插拔事件,举例来说,内核没有挂载根文件系统。

/etc/hotplug/*.agent这些脚本将被 hotplug
调用以响应内核产生的各种不同的热插拔事件,导致插入相应的内核模块和调用用户预定义的脚本。

/sbin/hotplug内核默认情况下将在内核态的某些事情发生变化时(如硬件的插入和拔出)调用此脚本。

发送热插拔事件的子系统(subsystem)包括总线驱动(USBPCI等)和一些设备的抽象层(网络接口、磁盘分区等)。它们通过/sbin/hotplug的第一个参数来识别。

对于设备驱动来说,需要在代码里设置 MODULE_DEVICE_TABLE ,指向驱动程序感兴趣的设备的设备 ID 列表。

udev

2.6内核里,使用了udev来取代hotplug。据udev的作者Greg K.H说,之所以废弃了hotplug原因是sysfs的出现,这个东西会产生非常多的hotplug事件,远远超过了2.4的内核(只要实现了了kobject模型的设备驱动都回产生该事件)。所以hotplug变得复杂,而且因为hotplug都是bash所写,所以开始变得没有效率。于是出现了一个名叫hotplug-ng的项目,就是为了解决这个过于复杂以及缺乏效率的问题,ng应该是next generation的意思。但这个项目目前为止还不能胜任角色,所以udev挺身而出,充当了救火队员。

2.6.15之后,/proc/sys/kernel/hotplug会成空的,因为内核通知用户空间的接口变成了netlink,所以最新的udev也采用了netlink接口去写,废弃了/sbin/hotplug或者/sbin/udevsendudev2.6.15以后的内核上可以直接通过netlink接听设备事件,sysfs提供了uevent文件,对该文件的可以送出设备事件!

udev 完全在用户态 (userspace) 工作,利用设备加入或移除时内核所发送的hotplug 事件 (event) 来工作。关于设备的详细信息是由内核输出 (export) 到位于 /sys  sysfs 文件系统的。所有的设备命名策略、权限控制和事件处理都是在用户态下完成的。与此相反,devfs 是作为内核的一部分工作的。

传统上一般 Linux 系统使用创建静态设备的方法,因此在 /dev 目录下创建了大量的设备节点(有时会有数千个节点),而不管对应的硬件设备实际上是否存在。这通常是由 MAKEDEV 脚本完成的,这个脚本包含许多调用 mknod 程序的命令,为这个世界上可能存在的每个设备创建相应的主设备号和次设备号。而使用 udev 方式的时候,只有被内核检测到的设备才为其创建设备节点。因为每次系统启动的时候都要重新创建这些设备节点,所以它们被存储在 tmpfs 文件系统上,设备节点不需要很多磁盘空间,所占用的内存可以忽略不计。

udev 初始化脚本负责在 Linux 启动的时候创建设备节点,该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事件(随后将讨论)本不应该在这个阶段发生,注册 udev 只是为了以防万一。然后 udevstart 遍历 /sys 文件系统,并在 /dev 目录下创建符合描述的设备。例如,/sys/class/tty/vcs/dev 里含有"7:0"字符串,udevstart 就根据这个字符串创建主设备号为 7 、次设备号为 0  /dev/vcs 设备。udevstart 创建的每个设备的名字和权限由 /etc/udev/rules.d/ 目录下的文件指定的规则来设置。如果udev 找不到所创建设备的权限文件,就将其权限设置为缺省的 660 ,所有者为 root:root 。上面的步骤完成后,那些已经存在并且已经内建驱动的设备就可以使用了。

对于以模块驱动的设备,当内核检测到一个新设备连接时,内核会产生一个热插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序(新的内核通知接口改变,/proc/sys/kernel/hotplug为空了)。udev
初始化脚本将 udevsend
注册为该处理程序。当产生热插拔事件的时候,内核让 udev  /sys 文件系统里检测与新设备的有关信息,并为新设备在 /dev 里创建项目。

所有在 sysfs 中显示的设备都可以由 udev 来创建节点。如果内核中增加了其它设备的支持,udev 也就自动地可以为它们工作了。

大多数 Linux 发行版通过 /etc/modules.conf 配置文件来处理模块加载,对某个设备节点的访问导致相应的内核模块被加载。对 udev 这个方法就行不通,因为在模块加载前,设备节点根本不存在。Linux 的设计是在设备被发现的时候加载模块,而不是当它被访问的时候。通过在 /etc/sysconfig/modules文件里添加模块名,就可以在系统启动的时候加载这些模块,这样 udev
就可以检测到设备,并创建相应的设备节点了。

如何写 udev 规则。通过 udevinfo 程序来找到那些可以作为规则文件里的匹配项的项目。分为两种情况:第一种情况是,当你把设备插入系统后,系统为设备产生了设备名(如 /dev/sda )。那样的话,你先用 udevinfo -q path -n /dev/sda ,命令会产生一个该设备名对应的在 sysfs 下的路径,如 /block/sda 。然后,你再用 udevinfo -a -p /sys/block/sda ,这个命令会显示一堆信息,信息分成很多块。这些信息实际来自于操作系统维护的 sysfs 链表,不同的块对应不同的路径。你就可以用这些信息来作为 udev 规则文件中的匹配项。但需要注意的是,同一个规则只能使用同一块中显示的信息,不能跨块书写规则;第二种情况是,不知道系统产生的设备名,那就只有到 /sys 目录下去逐个目录查找了,反复用 udevinfo -a -p /sys/path... 这个命令看信息,如果对应的信息是这个设备的,那就恭喜你。否则就再换个目录。当然,在这种情况下,成功的可能性比较小。
HAL

HAL位于设备驱动程序和应用程序之间。

l
D-BUS

D-BUS 是一个大有前途的消息总线和活动系统,正开始深入地渗透到 Linux 桌面之中。D-BUS 本质上是进程间通信(inter-process communication)(IPC)的一个实现,设计用于桌面应用程序和 OS 通信。

典型的 D-BUS 设置将由几个总线构成。一个持久的系统总线(system bus),它在引导时就会启动。这个总线由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件。还将有很多会话总线(session buses),这些总线当用户登录后启动,属于那个用户私有。

一个更为有趣但很不实用的例子是 Jamboree  Ringaling 的结合。Jamboree 是一个简单的音乐播放器,它具有 D-BUS 接口,以使得它可以被告知播放、到下一首歌、改变音量等等。Ringaling 是一个小程序,它打开 /dev/ttyS0(一个串行端口)并观察接收到的内容。当 Ringaling 发现文本“RING”时,就通过 D-BUS 告知 Jamboree 减小音量。最终的结果是,如果您的计算机上插入了一个调制解调器,而且电话铃响,则音乐音量就会为您减小。
这正是计算机所追求的!

l
一些查看硬件信息的工具

lspci
列出所有PCI 设备。有两个参数是比较常用,-b -vlspci也会把usb接口列出来。

lshal 列出系统硬件设备。

Usbmodules
列出可用于已插入 usb 设备的驱动模块

这篇关于Linux 热插拔(Hot Plug)处理机制系列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/805500

相关文章

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

Linux查询服务器 IP 地址的命令详解

《Linux查询服务器IP地址的命令详解》在服务器管理和网络运维中,快速准确地获取服务器的IP地址是一项基本但至关重要的技能,下面我们来看看Linux中查询服务器IP的相关命令使用吧... 目录一、hostname 命令:简单高效的 IP 查询工具命令详解实际应用技巧注意事项二、ip 命令:新一代网络配置全

Java异常捕获及处理方式详解

《Java异常捕获及处理方式详解》异常处理是Java编程中非常重要的一部分,它允许我们在程序运行时捕获并处理错误或不预期的行为,而不是让程序直接崩溃,本文将介绍Java中如何捕获异常,以及常用的异常处... 目录前言什么是异常?Java异常的基本语法解释:1. 捕获异常并处理示例1:捕获并处理单个异常解释:

linux安装、更新、卸载anaconda实践

《linux安装、更新、卸载anaconda实践》Anaconda是基于conda的科学计算环境,集成1400+包及依赖,安装需下载脚本、接受协议、设置路径、配置环境变量,更新与卸载通过conda命令... 目录随意找一个目录下载安装脚本检查许可证协议,ENTER就可以安装完毕之后激活anaconda安装更

Linux查询服务器系统版本号的多种方法

《Linux查询服务器系统版本号的多种方法》在Linux系统管理和维护工作中,了解当前操作系统的版本信息是最基础也是最重要的操作之一,系统版本不仅关系到软件兼容性、安全更新策略,还直接影响到故障排查和... 目录一、引言:系统版本查询的重要性二、基础命令解析:cat /etc/Centos-release详