- 系统:戴尔 Latitude 5591
- CPU i7-8850H
- GPU:集成Intel HD630(无专用GPU)
- USB-C 扩展坞:WD15
屏幕:2x Acer G226HQL(通过 HDMI 直接连接,并通过 DVI 至 miniDP 适配器连接到坞站)
操作系统:KDE neon 18.4
- 内核:5.3.0-45-generic
每次我重新插入坞站时,屏幕都会保持黑屏。我必须打开 xrandr(arandr、KDE 显示配置等)才能重新启用三屏布局。我怀疑这是由于端口名称不稳定造成的:
一切配置:
grep . /sys/class/drm/*/status
/sys/class/drm/card0-DP-1/status:disconnected
/sys/class/drm/card0-DP-2/status:disconnected
/sys/class/drm/card0-DP-5/status:connected # <---- 5
/sys/class/drm/card0-DP-7/status:connected # <---- 7
/sys/class/drm/card0-DP-8/status:disconnected
/sys/class/drm/card0-eDP-1/status:connected
/sys/class/drm/card0-HDMI-A-1/status:disconnected
/sys/class/drm/card0-HDMI-A-2/status:disconnected
/sys/class/drm/card0-HDMI-A-3/status:disconnected
现在,当我拔下并重新插入扩展坞时:
/sys/class/drm/card0-DP-1/status:disconnected
/sys/class/drm/card0-DP-2/status:disconnected
/sys/class/drm/card0-DP-6/status:connected # <---- 6
/sys/class/drm/card0-DP-8/status:connected # <---- 8
/sys/class/drm/card0-DP-9/status:disconnected
/sys/class/drm/card0-eDP-1/status:connected
/sys/class/drm/card0-HDMI-A-1/status:disconnected
/sys/class/drm/card0-HDMI-A-2/status:disconnected
/sys/class/drm/card0-HDMI-A-3/status:disconnected
DP-5
和DP-7
现在被称为DP-6
和DP-8
。数字每次都会改变。
如何防止这种情况发生?
编辑1:注意到可能相关的行为。我有一个监控 PCH 温度的温度小部件。每次重新启动后,它也会更改其名称。acpi/Thermal_Zone/1-pch_cannonlake/Temperature
几乎每次重新启动时,输入的数字都会改变。必须经常重新配置显示器。
编辑2:找一个arch 论坛上的帖子这描述了一个非常相似的问题。他们的解决方案是降级到内核 4.18。我目前正在运行4.18.0-25-generic
,似乎可以解决问题。
编辑2a:现在4.18.0-25-generic
我注意到了一个不同之处。的输出grep . /sys/class/drm/*/status
保持不变,每次重新连接时数字仍然会改变
grep . /sys/class/drm/*/status
/sys/class/drm/card0-DP-1/status:disconnected
/sys/class/drm/card0-DP-2/status:disconnected
/sys/class/drm/card0-DP-5/status:connected # <--- DP-5!
/sys/class/drm/card0-DP-6/status:connected # <--- DP-6!
/sys/class/drm/card0-DP-7/status:disconnected
/sys/class/drm/card0-eDP-1/status:connected
/sys/class/drm/card0-HDMI-A-1/status:disconnected
/sys/class/drm/card0-HDMI-A-2/status:disconnected
/sys/class/drm/card0-HDMI-A-3/status:disconnected
但xrandr
不知何故“看到”稳定的数字,如DP-1-1
和DP-1-2
:
xrandr -q | grep connected
eDP-1 connected 1920x1080+3839+0 (normal left inverted right x axis y axis) 344mm x 194mm
HDMI-1 disconnected (normal left inverted right x axis y axis)
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-2 disconnected (normal left inverted right x axis y axis)
DP-2 disconnected (normal left inverted right x axis y axis)
HDMI-3 disconnected (normal left inverted right x axis y axis)
DP-1-1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 509mm x 286mm
DP-1-2 connected primary 1920x1080+1919+0 (normal left inverted right x axis y axis) 509mm x 286mm
DP-1-3 disconnected (normal left inverted right x axis y axis)
在较新的内核上,xrandr 看到的数字与 drm 枚举的数字相同。
答案1
我遇到了类似的问题,并且认为在这篇文章中添加一些信息会很有用,以防其他人遇到与 X.org 和 /sys/class/drm 之间的端口 ID 更改相关的问题。
上https://bbs.archlinux.org/viewtopic.php?id=244118Arch Linux 线程,注意到一个关键:
少了 xrandr,多了 amdgpu。
为了进一步纠正这个问题,它不是 xrandr,xrandr 只是向用户公开 Xorg 端口 ID,正如您在 /var/log/Xorg.0.log 示例中看到的那样。
此外,当时降级内核以避免这种行为(至 4.18)的“解决方案”显然不是、也从来不是任何真正意义上的解决方案。
这里有几点需要注意:
每个 Xorg 驱动程序都有不同的行为方式,例如,当我们遇到这个问题时,有人挖出了相关的 amdgpu 代码,其中 DP-1 例如被 amdgpu 更改为 DisplayPort-0。当涉及到如何在内部处理端口 ID 时,需要比我能够访问的更多数据来确定每个 Xorg 驱动程序的行为。
我相信 /sys/class/drm 端口需要具有内核模式设置功能的驱动程序,并启用模式设置。这里有一个关于 drm / kms 的相当好的总结:http://trac.gateworks.com/wiki/linux/display 去引用:
DRM [直接渲染管理器] 是内核中的驱动程序子系统,能够与视频驱动程序(例如 Freescale I.MX6 处理器)进行通信。通过 ioctl() 调用,多个用户空间程序可以在任何给定时间绘制到显示器,因为 DRM 将管理这些请求。 DRM 还能够与图形处理器 (GPU) 连接,以便硬件加速这些请求。
DRM 驱动程序处理 DMA、AGP 内存管理、资源锁定和安全硬件访问。为了支持多个同步 3D 应用程序,必须将 3D 图形硬件视为共享资源。需要锁定来提供互斥。 DMA 传输和 AGP 接口用于将图形命令缓冲区发送到硬件。最后,必须有安全性来防止客户端使用图形硬件升级权限。
内核模式设置 (KMS) 是一种在内核空间而不是用户空间中设置显示分辨率、像素深度和屏幕刷新的方法。过去,这是由 X-Server 在用户空间中完成的。现代视频驱动程序(例如 IMX6 GPU 的 etnaviv 驱动程序)支持 KMS。 Linux 内核的 KMS 实现支持帧缓冲区中的本机分辨率,并允许即时控制台 (tty) 切换。 KMS 还支持 DRI2 等新技术,有助于减少伪影并提高 3D 性能。
这个级别的图形堆栈很难让您理解,但从我所看到的来看,/sys/class/drm 中的端口类似于 /dev/sdX 中的设备,它可以并且每次都会进行随机播放。启动,取决于检测顺序,而不是设备的实际情况。
到目前为止,我一直在寻找某种直接将 Xorg 端口 ID 与 /sys/class/drm ID 连接的方法,但没有成功,但到目前为止还没有找到这样的方法。看起来 Xorg 显示驱动程序确实有某种方法来创建“粘性”端口 ID,但不幸的是,它们还对这些 ID 应用相当随机的转换,这使得将它们直接连接到相关的 drm 端口 ID 比应有的困难得多。
这些转换可能是相当随机的,例如,在一张卡上,您可能有 drm ID eDP-1 和 Xorg ID eDP,或者 drm HDMI-A-1 和 Xorg HDMI-0,我相信这取决于特定的显示驱动程序,虽然我不知道 Xorg 内部是如何工作的。
看起来 Wayland(需要支持 KMS 的驱动程序)将始终显示相同的 ID,但需要注意的是,如果您使用 Xwayland 和 xrandr,xrandr 将显示 XWAYLAND0 ... 类型端口 ID,可能是因为这些 ID 实际上完全是从Xwayland 的硬件是我的猜测。
找到这些更改的明确明确的文档非常困难,特别是因为维护 Xorg 驱动程序的每个组基本上都可以自由地以他们喜欢的方式更改 ID。需要从不同的驱动程序、内核和硬件设置中获取更多样本才能真正确定这些变化的全部可能范围。例如,VGA-1 通常保留为 VGA-1,但也可能是 VGA0,这是相当随机的。
最好的解决方案是有某种方法来确定 /sys 中的物理端口 ID,即实际路径,然后确定 Xorg 中的物理端口路径,然后忽略 Xorg 和内核生成的 ID,但我目前还无法确定这一点。
我可能不认同其中一些观点/假设,如果是这样,任何修正都会受到赞赏,因为我也试图了解这实际上是如何在幕后工作的。
事情变得更加复杂,因为 nvidia 非免费驱动程序存在一些长期存在的错误,使 systemd 认为已连接和启用的监视器已被禁用,这可能会导致不希望的挂起操作。还有一些其他与 drm 数据相关的 nvidia 驱动程序错误根本没有出现。
此类 nvidia 非自由驱动程序错误的示例: https://forums.developer.nvidia.com/t/no-sys-class-drm-card0-entries-on-kernel-4-15/57855 https://forums.developer.nvidia.com/t/sys-class-drm-enabled-reports-disabled-for-enabled-monitors/51187
如果您的显示器都不同,您可以根据 Xorg 的 EDID 供应商和产品 ID (prod id) 以及序列号推断出 Xorg 为哪个显示器提供特定 ID:(但并非所有显示器都有序列号数据)。但我找不到任何方法以完全可靠且明确的方式将 Xorg 数据从端口 ID 和监视器信息链接到 pci 总线或 /sys/class/drm 信息。如果我确实找到了这种方法(这可能并不简单),我将更新这篇文章。
[更新] 感谢 mic_e 的评论,它显示从 2009 年左右开始(xrandr 1.2 及更高版本,于 2007 年左右发布,但在 2009 年左右在冻结池中发货) xrandr --prop / --property 将 CONNECTOR_ID 添加到输出,这可以是与 /sys/class/drm/*/connector_id 匹配以获得正匹配。这仅适用于 DRM 驱动程序/硬件,但现在大多数图形都是如此。
请注意,--prop 还显示 EDID 数据,尽管您可以直接从 /sys 获取该数据,因此这并不重要,并且 xrandr 无论如何只是另一个依赖项,但如果需要,您确实需要它匹配 drm 和 xorg 端口 ID。
如果您想要完全覆盖,并且不介意读取大量输出的开销,--verbose 总是有效,并在引入时触发 --prop。