![有时 GUI 响应缓慢 - 或根本不响应 - 或看起来崩溃 - 但光标仍然快速响应。鼠标指针如何工作?](https://linux22.com/image/155981/%E6%9C%89%E6%97%B6%20GUI%20%E5%93%8D%E5%BA%94%E7%BC%93%E6%85%A2%20-%20%E6%88%96%E6%A0%B9%E6%9C%AC%E4%B8%8D%E5%93%8D%E5%BA%94%20-%20%E6%88%96%E7%9C%8B%E8%B5%B7%E6%9D%A5%E5%B4%A9%E6%BA%83%20-%20%E4%BD%86%E5%85%89%E6%A0%87%E4%BB%8D%E7%84%B6%E5%BF%AB%E9%80%9F%E5%93%8D%E5%BA%94%E3%80%82%E9%BC%A0%E6%A0%87%E6%8C%87%E9%92%88%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%EF%BC%9F.png)
X.org X Windows 系统中鼠标光标是如何实现的?具体来说,我们应该如何理解这些错误情况:
1) 我记得有时会看到整个 GUI 变得缓慢、卡顿或停顿。但鼠标光标的反应仍然很快。例如,如果您使用太多内存并开始“抖动”,则可能会发生这种情况。 (系统不断地换出到磁盘并再次换回)。
2) 其他时候,Linux 图形驱动程序常常崩溃。屏幕可能被冻结、损坏或介于两者之间。但有时鼠标光标在冻结或损坏的显示之上仍然反应流畅。
鼠标光标损坏可能发生的一些问题(和解决方法)也有提示:
答案1
这里至少有两个单独的细节:
- 硬件光标
- 游标更新被刻意优先考虑
1. 硬件光标
第一个细节更为人所知。您可以在文档中找到它:HWCursor
Xorg 中的选项。
你的图形大概使用硬件光标。当硬件将像素扫描到显示器时,它将鼠标光标覆盖在主帧缓冲区的顶部。
- 图形驱动程序中的错误可能会错误配置帧缓冲区,而不会破坏硬件光标。
- 或者配置错误的硬件光标可能会出现损坏。但您可能仍然会看到损坏的光标移动并响应,而显示屏的其余部分似乎已损坏。
- 或者,当帧缓冲区正常时,光标可能配置错误。正如在“老鼠失踪“ 案件。
1.1 软件光标
请注意,虽然硬件光标非常有用,但也有一些技术可以使软件光标更好地工作。
https://www.x.org/wiki/Development/Documentation/InputEventProcessing/
如果是在软件中完成的,则必须对光标进行后台缓冲。每次移动时,我们都会恢复之前的图像,将窗口保存在目标位置,然后将光标渲染到流中。
xorg-server-1.20.5/mi/midispcur.c- miDCSaveUnderCursor() / miDCRestoreUnderCursor()
2. 刻意区分游标更新的优先级
公平地说,光标相对简单。此外,它还在不断使用。这意味着当您开始耗尽内存时,特定于游标的内存不太可能被换出。但还有一个细节:
https://who-t.blogspot.com/2016/09/input-threads-in-x-server.html
以前,输入驱动程序如何将事件传递到 X 服务器有两种选择:轮询或从信号处理程序内传递。轮询只是将所有输入设备的文件描述符添加到在服务器主循环中处理的 select(2) 循环。这里的缺点是,如果服务器正忙于渲染某些内容,您的输入将被延迟,直到渲染完成。从历史上看,轮询主要由键盘驱动程序使用,因为当击键延迟时它并不重要。两者都是因为你需要客户端无论如何渲染它们(当它很忙时它不能渲染它们),也可能是因为我们太习惯于打字延迟了。
信号处理程序方法通过为每个输入设备 fd 安装一个 SIGIO 处理程序并在发生任何输入时调用该处理程序来避免延迟。这会有效地中断进程,直到信号处理程序完成,无论服务器当前忙于什么。一个很好的解决方案提供即时可见的光标移动 (因此它被 evdev、synaptics、wacom 和大多数现已退役的旧版驱动程序使用)
[...]
驱动程序在信号处理程序期间将事件推送到队列中,在主循环中服务器读取并处理它们。在繁忙的服务器中,在屏幕上执行指针移动后可能需要几秒钟,但是嘿,它仍然感觉响应良好。
[...]
在 libinput 出现之前,我们仍然对它感到“满意”。 libinput 是一个完整的输入堆栈,期望它在信号处理程序中工作是介于乐观、受虐和虐待之间的。 xf86-input-libinput 驱动程序不使用信号处理程序,其副作用是,当服务器忙于渲染时,带有 libinput 的桌面感觉响应不灵敏。
Keith Packard 介入并将服务器从信号处理程序切换为使用输入线程。或者更具体地说:主线程之上的一个输入线程。该线程控制所有输入设备的文件描述符并连续读取它们的事件。除此之外,它提供了与信号处理程序之前相同的功能:可见的指针移动以及将事件推送到事件队列中,以便主线程稍后处理它们。但是,当然,一旦您切换到线程,问题就会出现了。 [...]一些有趣的竞争条件不断发生。但截至今天,我们认为大部分问题都已解决。