为什么 windows 在内核中处理滚动条?

Why does windows handle scrollbars in kernel?

"all" windows 的新 1-bit exploit 版本在处理滚动条的内核代码中使用了一个错误。这让我开始思考。为什么 windows 在内核而不是用户模式下处理滚动条?历史原因?有其他 OS 这样做吗?

TL;DR:微软为了性能牺牲了安全性。


Windows 上的滚动条有点特别。大多数滚动条不是真正的 windows,而是在 "parent" window 上实现为 decorations。这引出了一个更普遍的问题;为什么 windows 在 Windows 上以内核模式实现?

让我们看看备选方案:

  1. 用户模式下的每个进程。
  2. 用户模式下的单个 "master" 进程。

备选方案 1 在处理 你自己的 windows 时有很大的优势;没有上下文 switch/kernel 转换。问题当然是来自不同进程的 windows 存在于同一屏幕上,并且必须有人负责决定哪个 window 处于活动状态,并且当用户切换到不同的 window 时坐标会发生变化.这个人必须是一个特殊的系统进程或内核,因为这个信息不能是每个进程的,它必须存储在全局的某个地方。这种双重信息设计将变得复杂,因为全局 window 管理器无法信任每个进程的信息。我敢肯定这个理论设计还有很多其他缺点,但我不会在这里花更多时间。

Windows NT 3 实现了备选方案 2 的变体。window 管理器在 NT 4 中被移入内核模式,主要是为了 performance reasons:

...the Window Manager (USER) and Graphics Device Interface (GDI) have been moved from the Win32 subsystem to the Windows NT Executive. Win32 user-mode device drivers, including graphics display and printer drivers, have also been moved to the Executive. These changes are designed to simplify graphics handling, reduce memory requirements, and improve performance.

...在同一文档的下方还有更多技术细节和理由:

When Windows NT was first designed, the Win32 environment subsystem was designed as a peer to the environment subsystems supporting applications in MS-DOS, POSIX, and OS/2. However, applications and other subsystems needed to use the graphics, windowing, and messaging functions in the Win32 subsystem. To avoid duplicating these functions, the Win32 subsystem was used as a server for graphics functions to all subsystems.

This design worked respectably for Windows NT 3.5 and 3.51, but it underestimated the volume and frequency of graphics calls. Having functions as basic as messaging and window control in a separate process generated substantial memory overhead from client/server message passing, data gathering, and managing multiple threads. It also required multiple context switches, which consume CPU cycles as well as memory. The volume of graphics support calls per second degraded the performance of the system. It was clear that a redesign of this facet in Windows NT 4.0 could reclaim these wasted system resources and improve performance.

这些天其他子系统不那么相关,但性能问题仍然存在。

如果我们看一个像 IsWindowVisible 这样的简单函数,那么当 window 管理器处于内核模式时,不会有太多开销:该函数将在用户模式下执行几条指令然后将 CPU 切换到环 0,整个操作(验证传入的 window 句柄,如果有效,检索可见的 属性)在内核模式下执行。然后它会切换回用户模式,仅此而已。

如果 window 管理器存在于另一个进程中,那么您将至少使内核转换的数量增加一倍,并且您必须以某种方式将函数输入和输出传递给 window 管理器进程,并且您必须以某种方式使 window 管理器进程在您等待结果时执行。 NT 3 通过结合使用共享内存 LPC 和称为配对线程的晦涩功能来做到这一点。