百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

linux udev详解4-Storage Instantiation Daemon(2)

suiw9 2025-03-26 16:56 5 浏览 0 评论

此文章翻译自:Storage Instantiation Daemon (sid-project.github.io)。

强烈推荐看下此文章,不仅对之前的udev内容做了部分补充,更能加强对udev的理解。工作中涉及有udev的道友可以看下原文。

先决条件

udevd内置命令-sid

在udevd和存储实例化守护程序(SID)之间建立一个通信通道,以便能够在两者之间有效地交换信息。

udevd支持实现内置命令,这些命令在udevd启动时初始化,并在udevd停止时完成。这样udevd在处理每个uevent时不需要fork新进程,就像在udev规则中引用外部命令时。

在udev规则中调用内置命令方式与调用任何外部命令非常相似,在规则中使用RUN{builtin}或IMPORT{builtin}即可。

注意:udevd内置命令使用内部模块化接口直接集成到udevd源代码中。udevd不支持外部和动态加载的模块实现此功能。

udevd和SID之间的通道使用本地流和面向连接的socket IPC实现(AF_UNIX/AF_LOCAL socket域,SOCK_STREAM socket类型)。

如果udevd创建了一个新的worker进程,连接将在第一次调用sid内置命令时建立,并保持打开状态,直到worker进程退出(或在超时的情况下被udevd进程终止)。

由于我们使用流和面向连接的通道,接收方(SID)可以检测到对方(worker进程)的断连。这样,SID能够检测到worker进程超时并在意外发生断连时触发后续的回退操作。

sid支持的子命令

  • sid active

目的: 检查SID的可用性。

输入: None

输出: SID_BRIDGE_STATUS=,其中有以下值:

  • active:表示SID的兼容版本正在运行,
  • inactive:表示未运行,
  • incompatible:表示SID正在运行,但其版本与当前sid udevd内置命令不兼容。

示例:

IMPORT{builtin}="sid active"
ENV{SID_BRIDGE_STATUS}=="active", ...
ENV{SID_BRIDGE_STATUS}=="incompatible", ...
ENV{SID_BRIDGE_STATUS}=="inactive", ...
  • sid scan

目的: 执行SID的识别和扫描程序、更新SID数据库、执行相关操作;

输入: 以KEY=VALUE格式表示的udev环境;

输出: 以KEY=VALUE格式表示的环境,其中包含changed或added的项目。

示例:

 IMPORT{builtin}="sid scan"
  • sid checkpoint [ ...]

目的: 向SID发送关于匹配checkpoint的消息。

输入: 在匹配udev规则时达到的。还可以传递一个从当前udev环境引用的键列表(或者使用all关键字表示所有可用键)。除了checkpoint名称本身,该命令还将从当前udev的每个设备环境向SID发送选定的KEY=VALUE。有一个预留的checkpoint:complete,用于通知SID udev规则中的udev处理即将结束。

输出: None。

注: 安装或启用其他udev规则可以使用checkpoint进行调试,这些规则将在SID执行时执行,以便SID能够跟踪uevent处理的进展。

示例

PROGRAM{builtin}="sid checkpoint my_checkpoint A B C" 
RUN{builtin}="sid checkpoint complete"
  • sid version

目的: 返回sid udevd内置命令和SID程序的版本信息。

输入: None。

输出: 一组KEY=VALUE:

  • SID_PROTOCOL=
  • SID_MAJOR=
  • SID_MINOR=
  • SID_RELEASE=
  • SID_BUILTIN_PROTOCOL=
  • SID_BUILTIN_MAJOR=
  • SID_BUILTIN_MINOR=
  • SID_BUILTIN_RELEASE=

注: 尽管可以在udev规则中调用sid version,但更合理的是将其作为udevadm test-builtin命令的一部分进行调用,用于收集当前系统环境的调试和版本信息。请注意,udevadm test-builtin命令需要给定一个现有设备的sysfs路径作为参数。sid version内置命令不与任何设备绑定,因为它只收集版本信息,所以可以在这里使用任意现有的sysfs路径来满足要求。

示例:

# udevadm test-builtin "sid version" /sys/kernel
SID_PROTOCOL=1
SID_MAJOR=0
SID_MINOR=0
SID_RELEASE=1
SID_BUILTIN_PROTOCOL=1
SID_BUILTIN_MAJOR=0
SID_BUILTIN_MINOR=0
SID_BUILTIN_RELEASE=1

增强synthetic-uevents

在处理uevents时需要考虑并不是所有uevents都是直接在内核中触发的,还有用户空间触发的合成uevents(如将事件写入/sys/.../uevent文件)。为了能够更好地区分synthetic-uevents和kernel-uevents,需要增强synthetic-uevent接口。

  1. 内核增加支持增强的synthetic-uevents特性

增强synthetic-uevents接口在写入/sys/…/uevent文件时可以传递附加参数。

提议是在事件名称中传递一个唯一标识符,将生成的uevent标记为事务的一部分。该事务可以跨越一个或多个uevents。该标识符将作为环境变量出现在生成的uevent中。如果我们使用一个标识符和多个uevents,我们将它们逻辑上组合在一起 - 在这种情况下,任何读取这些uevents的用户空间进程都可以观察和/或收集组中的所有成员。此外,通过这种方式,可以与合成uevent处理进行同步,并且在继续后续处理之前,我们可以等待组中的所有更改稳定下来。

以前无法等待单个uevent处理完成,只能使用udevadm settle命令等待所有uevent处理完,该命令将等待很多无关的uevents。

为了向后兼容,synthetic-uevents不需要标识符,内核只是自动添加一个值为零的标识符。

注意:使用UUID表示标识符 ,UUID可以使用工具生成(如util-linux工具集的uuidgen)或使用各种库(如util-linux的libuuid或libsystemd的sd-id128)。

用户空间进程触发synthetic-uevents可以追加环境变量,追加的KEY=VALUE环境变量列表需要在标识符之后。另外KEY和VALUE要求必须是字母和数字,每个KEY=VALUE之间用空格隔开。为了避免现有udev环境变量键的名称冲突,写/sys/.../uevent文件时内核将自动在每个KEY前添加SYNTH_。

以下是增强的synthetic-uevent接口使用示例:

# uuid=$(uuidgen)

# echo $uuid
4f60b88c-3052-4daa-8904-2e4efe8563ef

# echo "change 4f60b88c-3052-4daa-8904-2e4efe8563ef A=1 B=abc" > /sys/block/sda/uevent
# 监听输出结果
#udevadm monitor -k -u  -p
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:10.0/host32/target32:0:0/32:0:0:0/block/sda
SUBSYSTEM=block
SYNTH_UUID=0b591ea4-10d4-431a-b663-7528c6e9043b
SYNTH_ARG_A=1
SYNTH_ARG_B=abc

sys/.../uevent接口仍然保持向后兼容,可以只写入事件(add\change等)触发,不追加额外的变量仍然可以工作

# echo "change" > /sys/block/sda/uevent
# udevadm monitor --kernel --property
DEVPATH=/devices/pci0000:00/0000:00:08.0/virtio4/host2/target2:0:0/2:0:0:0/block/sda
DEVTYPE=disk
MAJOR=8
MINOR=0
SEQNUM=2028
SUBSYSTEM=block
SYNTH_UUID=0

上面示例中SYNTH_UUID=0是内核自动添加的,即使在写入/sys/.../uevent来生成synthetic-uevent时没有使用额外的参数,仍然可以在处理它们时区分kernel-uevent和synthetic-uevents,synthetic-uevents始终包含SYNTH_UUID键。

注意:增强的synthetic-uevent接口kernel版本4.13才开始支持。

  1. OPTIONS+="watch"规则增强的synthetic-uevents特性

作为应用OPTIONS+="watch"规则的结果生成的所有synthetic-uevents将包含以下KEY=VALUE对:

SYNTH_UUID="00000000-0000-0000-0000-00000000000" 
SYNTH_ARG_UDEV_WATCH="1" 

这意味着,每次udev写入/sys/.../uevent文件生成synthetic-uevents时,它将使用以下字符串触发uevent:

change 00000000-0000-0000-0000-00000000000 UDEV_WATCH=1 

在基于OPTIONS="watch"规则生成的synthetic-uevents中使用空UUID是因为这里没有任何作用,预留以后使用。

  1. udevadm trigger增强的synthetic-uevents特性

udevadm trigger调用生成的所有合成uevents将包含以下KEY=VALUE对:

SYNTH_UUID="" 
SYNTH_ARG_UDEV_TRIGGER="1"


这意味着,每次udev写入/sys/.../uevent文件生成synthetic-uevents时,将使用此字符串触发uevent:

  UDEV_TRIGGER=1                 

是使用-c,--action=ACTION参数提供的ACTION。 通过使用新的--uuid=UUID参数传入。 UUID然后用于触发所有的uevents,所有的uevents按照此UUID组合成单个事务。如果未指定UUID,则udevadm trigger会生成一个随机UUID。

此外,udevadm trigger有个新的参数-wait-uevent,作用是在退出之前等待udev中的所有相关uevent处理(包括所有udev规则处理)完成。

例如,要为所有属于块子系统的设备触发change uevent,并在退出udevadm trigger之前等待udev中的所有相关uevent处理完成,命令如下:

udevadm trigger --subsystem-match block --action change --wait-uevent

要为所有属于块子系统的设备触发change uevent,并使所有生成的uevents在uevent环境中设置UUID为
6cab53e2-b9c9-4c43-9d1d-0d8673fb62b0,命令如下:

udevadm trigger --subsystem-match block --action change --uuid 6cab53e2-b9c9-4c43-9d1d-0d8673fb62b0
  1. libudev支持增强synthetic-uevents

libudev库包含有生成synthetic-uevent的函数,函数原型如下:

int udev_device_synth_uevent(struct udev_device *udev_device, const char *action, bool wait, unsigned long long timeout);

该接口为udev_device生成类型为action的synthetic-uevent。如果wait为true,函数将在内部设置uevent监视器以等待对应的udev uevent,并在收到uevent或timeout时退出。

使用device_synth_uevent函数生成的所有synthetic-uevents都将包含以下KEY=VALUE对:

SYNTH_UUID="" 
SYNTH_ARG_LIBUDEV_TRIGGER="1"

这意味着,每次在此场景中libudev写入/sys/.../uevent文件以生成synthetic-uevents时,将使用此字符串触发uevent:

  LIBUDEV_TRIGGER=1

未来可能会提供更多的函数来扩展此功能,并通过libudev库提供类似于udevadm trigger的功能。

最终,各种工具和用户空间组件建议使用这个接口,而不是依赖于OPTIONS+="watch"规则。

相关推荐

Qt编程进阶(99):使用OpenGL绘制三维图形

一、Qt中的OpenGL支持...

OpenGL基础图形编程(七)建模(opengl教程48讲)

七、OpenGL建模  OpenGL基本库提供了大量绘制各种类型图元的方法,辅助库也提供了不少描述复杂三维图形的函数。这一章主要介绍基本图元,如点、线、多边形,有了这些图元,就可以建立比较复杂的模型了...

ffmpeg cv:Mat编码成H265数据流(ffmpeg编码mp4视频)

流程下面附一张使用FFmpeg编码视频的流程图。使用该流程,不仅可以编码H.264的视频,而且可以编码MPEG4/MPEG2/VP8等等各种...

986g超轻酷睿本,联想ThinkPad X1 Carbon 2025 Aura评测

今年3月份,联想首发了搭载Intel酷睿Ultra移动平台的ThinkPadX1CarbonGen12轻薄本,其续航表现令人惊喜。时隔9个月,IT之家收到了ThinkPad...

拆解五六年前的国产平板,这做工!

之前在论坛有幸运得被抽到奖,就是猎奇手机镜头,到手的时候玩了下鱼眼和广角微距,效果见图,用手机拍的那么就进入正题来说下拆鸡过程,外壳我就不拍出来了,免得打广告之嫌,拆出背面外壳就出现了一个裸板。第...

什么是闭合GOP和开放GOP?(闭合式和开放式区分)

翻译|Alex技术审校|李忠本文来自OTTVerse,作者为KrishnaRaoVijayanagar。...

拆解五六年前的国产平板(国产平板怎么拆开)

之前在论坛有幸运得被抽到奖,就是猎奇手机镜头,到手的时候玩了下鱼眼和广角微距,效果见图,用手机拍的那么就进入正题来说下拆鸡过程,外壳我就不拍出来了,免得打广告之嫌,拆出背面外壳就出现了一个裸板。第...

如何使用PSV播放MP4 视频自动退出怎么办

作者:iamwin来源:巴士论坛(点此进入)看到有很多同学在为psv无法播放视频而困扰,自己研究了下,发一个可以解决PSV出现播放视频播放到一半就跳出的问题。就是这个问题:首先,请大家先升级到版本≥1...

2023-03-21:音视频解混合(demuxer)为MP3和H264...

2023-03-21:音视频解混合(demuxer)为MP3和H264,用go语言编写。答案2023-03-21:...

FFmpeg解码H264及swscale缩放详解

本文概要:...

CasaOS保姆级喂饭教程!网心云OEC-Turbo安装CasaOS系统固件!

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:柒叶君...

Firefox 33将整合思科开源编解码器OpenH264

思科去年在BSD许可证下开源了支持H.264编解码的OpenH264,Mozilla则在当时宣布将在Firefox中整合思科的二进制模块。现在,最新的FirefoxNightly(Firefox3...

为什么传输视频流的时候需要将YUV编码成H.264?

首先开始的时候我们借用一张雷神的图帮助大家理解一下从上图可以看出我们要做的,就是将像素层的YUV格式,编码出编码层的h264数据。...

FFmpeg学习(1)开篇(ffmpeg开发教程)

FFmpeg学习(1)开篇...

喜欢看视频必须了解 AV1编码那点事

喜欢看视频的小伙伴大概都有点感觉,AV1这个不太熟悉的视频格式,最近闹出的事情可不少,比如视频网站为了节约带宽偷偷默认使用AV1格式,让电脑狂转;比如Intel专门给旧CPU发布了相关工具;再比如GP...

取消回复欢迎 发表评论: