linux使用udev实现hdmi设备插拔事件

文章讲述了如何通过udev规则管理工具处理hdmi设备的插入和拔出事件,通过udevadmmonitor和udevadminfo获取设备信息,创建自定义规则文件来在change事件发生时启动或关闭应用,以及解决响应脚本导致程序被意外结束的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

技术需求,在插入hdmi接口的时候打开扩展屏应用程序,在拔出的时候关闭应用程序

udev

udev介绍

使用udev查询触发哪个事件

运行udev实时监视命令,然后拔插设备,观察输出信息

udevadm monitor

在这里插入图片描述
插入hdmi:
在这里插入图片描述
拔出hdmi:
在这里插入图片描述
观察输出可以发现,插入和拔出内核都是发送的change事件,而不是add/remove事件,容易踩坑。同时可以从后面看出系统显示设备的路径,这里截取后面的路径即/drm/card1,因此可以得到该显示驱动路径:/sys/class/drm/card1
一般显示设备都会在/sys/class/drm路径下:
在这里插入图片描述
不确定的话可以去某个文件下用cat读取status文件可以获取其状态,在插拔一下确认状态是否正确改变:
在这里插入图片描述

通过udev查询详细信息

使用上面确认后的设备路径,执行下面命令:

udevadm info --attribute-walk --path=$(udevadm info --query=path --path=/sys/class/drm/card1-HDMI-A-1)

在这里插入图片描述
通过命令的输出可以确认KERNELS和SUBSYSTEMS的值,于是编写udev的规则文件99-custom-hdmi.rules

sudo vim /etc/udev/rules.d/99-custom-hdmi.rules

加入如下内容:

ACTION=="change", KERNEL=="card1", SUBSYSTEMS=="drm", RUN+="/path/to/your/script.sh"

其中,捕获事件设置为change,KERNEL值设置为card1-HDMI-A-1,但实测这个值不起作用,于是设置为其父设备的值,SUBSYSTEMS的值设为drm,RUN中为事件响应时执行的脚本。
然后使配置文件生效:

udevadm trigger

这里我也设置不起作用,于是还是重启试试。

事件响应脚本

在响应脚本中执行你要处理的事情,我的脚本是启动扩展屏程序。
由于设备的插入或者拔出都是触发的change事件,所以需要在响应脚本中手动判断是插入或拔出。我的判断逻辑是读取设备文件的状态文件/sys/class/drm/card1/card1-HDMI-A-1/status,插入时该状态是connected,拔出时为disconnected,代码:

#!/bin/bash  

# 读取HDMI连接状态
status=$(cat /sys/class/drm/card1-HDMI-A-1/status)
tty=/dev/pts/0
# 拔出事件
if [ "$status" = "disconnected" ]; then 
    echo "HDMI disconnected..." > $tty
# 插入事件
else   
    echo "HDMI connected..." > $tty
fi

由于脚本不在tty中执行,因为需要指定tty才能接收到输出信息,可以在终端中使用tty命令查看当前终端位置:
在这里插入图片描述
ok,这下插拔时就会有相应的响应了,上面脚本只是示例脚本,实际我在插入事件中启动我的应用,在拔出事件中杀掉应用。
注意:*.rules规则文件修改后必须重启生效,而响应脚本修改后不需要重启即生效。

problem:在脚本中执行我的程序,事件响应后会直接杀掉该程序

无论我的启动方式是后台还是挂起,脚本执行完毕后都会杀掉程序
我们打印执行前后的进程树:pstree -up
执行事件处理时:
在这里插入图片描述
执行事件处理后:
在这里插入图片描述
也是通过这一步才发现原来脚本执行后就会杀掉程序,不知道什么原因,但是这种处理方式肯定不行。
后面想到了把应用程序注册为服务,在响应脚本中启动服务,这样应用程序的进程与响应脚本的进程独立,不受影响。

第一次写,记录一下工作中遇到的问题,文笔不好切莫责怪,感谢支持~~~

将可移动设备连入系统时,系统的后台中会依次发生如下事件: l 内核检测到新硬件插入,然后分别通知hotplug和udev。前者用来装入相应的内核模块(如usb-storage),而后者用来在/dev中创建相应的设备节点(如/dev/sda1)。 l udev创建了相应的设备节点之后,会将这一消息通知hal的守护程序(hald)。当然udev还得保证新创建的设备节点可以被普通用户访问。 l hotplug装入了相应的内核模块之后,会把这一消息通知给hald。 l hald在受到hotplug和udev发出的消息之后,认为新硬件已经正式被系统认可了。此时它会通过一系列精心编写的规则文件(就是传说中的xxx-policy.fdi),把发现新硬件的消息通过dbus发送出去,同时还会调用update-fstab或fstab-sync来更新/etc/fstab,为相应的设备节点创建适合的挂载点。 l 卷管理器会监听dbus中发现新硬件的消息。根据所插入的硬件(区分U盘和数码相机等)不同,卷管理器会先将相应的设备节点挂载到hald创建的挂载点上,然后再打开不同的应用程序。 当然,如果是在CDROM中插入光盘,过程可能比较简单。因为CDROM本身就是一个固定的硬件,无需hotplug和udev的协助: l hald会自己监视CDROM,并且将光盘托架开合的消息通过dbus发出去。 l 卷管理器负责检查CDROM中的盘片内容,进行挂载,并调用合适的应用程序。 要注意,hald的工作是从上游得到硬件就绪的消息,然后将这个消息转发到dbus中。尽管它会调用程序来更新fstab,但实际上它自己并不执行挂载的工作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值