Linux 2.2 和帧缓冲控制台
Linux 是一个引人入胜且节奏快速的野兽。 仿佛昨天 Linux 内核的坚定开发者们还在忙着为 ELF 支持、可加载模块和 SMP(对称多处理)——这些我们今天视为理所当然的东西——做最后的润色。 在那些日子里,更多的时间花在了关键的障碍上,这些障碍将使 Linux 成为今天伟大的服务器平台。 在今天的 Linux 世界中,更多的时间花在了系统不太重要的组件上:新的文件系统、电视和无线电卡以及并行端口驱动器。 我觉得世界各地的公司对操作系统的兴趣增加,将使未来支持更多“非关键”硬件。
Linux 2.2 是 Linux 开发的一个里程碑。 Linux 不再是一个小众操作系统——它已成为大众可行的解决方案。 凭借对如此多新选项的支持,这不足为奇。
文本模式是 Linux 最基本的输出方法,也是 Linux 自“旧”时代以来几乎没有改变的一个领域。 Linux 2.0 的文本模式控制台非常纯粹和简洁,其中一个显而易见(也许令人震惊)的事实是:内核中没有图形原语的代码。 文本模式内核的最低级别接口就像文件流一样简单。 更高级别的函数,例如全屏文本控制台应用程序(Pine 等)所需的函数,是通过 vt100 终端协议的超集完成的。 诸如 ncurses 之类的库构建在其之上,以简化编程并提供某种终端抽象。 为 Linux 文本模式控制台编写的使用此抽象的应用程序几乎可以在任何终端上运行。 回溯一下,Linux 著名的虚拟控制台并不是这些基本构建块的复杂扩展,而是在文本模式驱动程序与它所设计的 VGA 硬件的密切关系的基础上提供的扩展。
还存在其他实用程序,例如 SVGATextMode,它允许我们访问文本模式下硬件的一些图形功能。 这些实用程序通常允许更改文本分辨率、字体和颜色。 但是,这些扩展直接与 VGA 功能接口,并且不调用内核中的任何扩展。 通常,Linux 控制台的设计非常模块化,以至于它没有注意到低级别的 VGA 功能更改。 这些实用程序不应与 SVGALib 或帧缓冲控制台混淆,因为它们只允许在硬件的文本模式下进行操作。
显然,现代硬件不仅仅是简单的文本模式。 如前所述,内核钩子没有为访问这些功能而提供,但是许多用户空间程序和库可用,它们完全绕过内核以访问底层的硬件。 (“用户空间”是一个术语,用于描述用户程序运行的受限和受保护的“空间”。 相比之下,“内核空间”例程通常不受保护,可能会导致崩溃和其他问题。 可以删除用户保护,以允许用户程序访问硬件。) 不幸的是,对于最流行的替代方案 SVGALib,它提供的支持 API 与 VGA 硬件的功能紧密相关,这使得将 SVGA 库或最终应用程序移植到任何其他类型的硬件变得困难。 另一个缺点是该库并非以其全部潜力支持所有 VGA 硬件,但这可以原谅,因为硬件设计变化无常。 撇开局限性不谈,SVGALib 已被证明是控制台问题的一个稳定且流行的解决方案,并且是 Quake 和其他游戏中使用的主要接口。
在 Linux 下访问视频硬件的最终也是最流行的选择是通过 X Window 系统,这是 UNIX 最常见的 GUI 子系统。 X Window 系统包括一个“X 服务器”,其目的类似于 Windows 风格的视频驱动程序。 除了“驱动程序”功能外,X 服务器还包括通过网络运行程序和内部处理许多 GUI 任务的代码。 在这方面,“驱动程序”部分与“服务器”部分并非真正分离。 希望访问视频硬件的程序将通过其 API 与 X 服务器进行通信。
这种方法的第一个也是最明显的缺点是,在某些设置上,通过这种方法运行“控制台”(全屏)应用程序将非常困难,甚至不可能。 其次,由于 X 系统的驱动程序/服务器功能相结合,服务器往往非常庞大,使得在低内存情况下难以运行程序。 这种方法的第三个缺点是,公司通过销售用于新硬件的闭源 X 服务器来获利是很常见的。 但是,这个系统的主要优点是,拥有一个长期存在且跨平台的支柱来构建图形应用程序,这似乎超过了缺点。
到目前为止,我甚至还没有提到帧缓冲在当前 Linux 内核中扮演的角色。 帧缓冲控制台系统在其他几个 UNIX 系统以及几个 Linux 版本(特别是 Linux/m68k 和 Linux/PPC)中已经存在相当长一段时间了。 在这些平台上使帧缓冲控制台如此重要的原因是:并非所有视频硬件都支持内置文本模式。 在这些系统上,帧缓冲控制台不是带来启动徽标的新奢侈品,而是功能的必要条件。 在这些系统上,情况略有不同。 它们当然仍然有 X,并且 X 是以设备无关的方式创建应用程序的绝佳方法。 专门为处理帧缓冲系统而设计的特殊 X 服务器几乎总是可用的。 这些系统的情况也得到了简化,因为没有库可以使它们运行 SVGALib 应用程序。
在当前的实现下,在处理图形子系统时,必须提出许多安全问题。 部分原因正是这些安全隐患,帧缓冲控制台才成为 Linux 2.2 内核的一部分。
必须通过内核 API 提供对用户程序的硬件访问,该 API 提供设备抽象层。 为了保持系统安全且无崩溃,内核接口必须经过仔细设计,因为在内核中可能会造成最大的损害。 访问硬件是危险的; 如果用户程序可以直接访问硬件,则很容易使机器崩溃。 此外,设计不良的内核接口可能会泄露有关用户的敏感数据,无论多么难以利用的安全漏洞,在 Linux 开发者社区中都非常重视。 虽然内核中没有直接硬件访问的规定,但可以使用某些解决方法来规避这些限制——以尽可能安全的方式。
“没有直接访问”规则有两个例外。 第一个是简单的:对于 root 运行的程序,系统管理员(通常应该知道她在做什么)可以直接访问任何文件和任何硬件。 实际上,对于 root 可以做什么几乎没有限制。 但是你肯定不希望你的用户拥有 root 密码并在每次他们想运行 Quake 时都使用它,对吗? 第二个例外是此问题的解决方案:程序的所有者(通常是 root)可以在程序上设置一个名为“setuid 位”(设置用户 ID)的标志,允许普通用户在程序方面“成为”其他用户。 因此,如果 root 拥有该文件并且设置了 setuid 位,则该程序将始终具有 root 访问权限,因此将始终能够直接访问硬件。 在这种特殊且受到良好控制的情况下,最终用户可以运行他们的 Quake 或他们的 X 服务器,尽管他们通常无法直接访问硬件。
但是请注意,并非所有图形程序都需要“setuid root”才能运行。 特别是 X 程序不直接访问任何硬件。 相反,它们通过 API 与 X 服务器通信,然后将它们想要执行的操作转换为视频硬件。 相比之下,SVGALib 应用程序通常都需要具有特殊权限才能正常运行。
让任意程序以 root 身份运行的安全隐患应该是显而易见的。 Linux 目前没有一种方法来说明特定程序可以“仅仅”访问任何文件或“仅仅”直接访问硬件——这方面的工作正在进行中。 相反,“setuid root”应用程序可以做任何事情,包括关闭服务器。 说到拒绝服务! 因此,必须非常仔细地编写这些应用程序,以使错误的用户不会执行任何可能违反盒子安全性的操作。 站点的管理员有责任维护和确保仅在绝对必要时才使用这些特殊程序,否则将导致巨大的安全漏洞。
即使是精心编写的程序有时也可能通过“堆栈粉碎”被破解以获得 root 访问权限,如果程序员不确保监视其缓冲区并使用更安全的例程,如 strncpy 而不是 strcpy。 通常,编写“setuid root”应用程序的程序员应该注意整个程序中使用的任何缓冲区。 记录在案,strcpy 和 strncpy 都是将文本数据(字符串)从内存中的一个位置复制到另一个位置的函数。 strncpy 中的“n”表示要复制的最大字符数。 否则,攻击者可能会以某种方式操纵数据,使要复制的数据大于要复制到的位置,并且多余的数据会覆盖内存。 如果他们技术娴熟,这种多余的数据可能包括程序代码,然后可以运行该代码以闯入 shell 或造成其他损害——并且它将以 root 身份执行。
在底层,Linux 2.2 的文本模式被设计成一个更模块化的系统,具有定义的接口,并且更少依赖于 VGA 硬件内部结构。 随意的观察者不会注意到这些改进中的任何一个。 这与我们一直喜爱的文本模式相同。 但是,进行了改进,以允许机器在没有视频硬件的情况下获得更好的串行控制台,并允许关闭虚拟控制台,但这些功能并非文本模式驱动程序明确的一部分。
对于 i386 而言,帧缓冲设备是 Linux 2.2 最新的视频功能。 与早期版本的 Linux 不同,通过帧缓冲设备可以直接且以设备无关的方式访问机器的视频硬件。 支持所有基本的图形原语,尽管目前通常不支持加速。 加速架构将如何适应仍然是一个争论的问题。 有些人指向用户模式程序和库(例如 GGI); 另一些人则认为,至少某些类型的加速的最佳位置是在内核中。 请注意,与文本模式驱动程序相反,没有字符单元显示——它在其他地方处理。 SVGALib 应用程序以及在较小程度上 X 应用程序都可以获得对视频硬件大致相同的控制级别,但它们通常可移植性较差且安全风险更高。
除了这些功能之外,现在还可以通过使用设备节点(就像任何其他设备一样)来访问帧缓冲设备。 例如,这些设备节点 /dev/fd* 可以用于通过执行标准复制命令来获取屏幕截图。
帧缓冲之上是帧缓冲控制台 (fbcon)。 这是实现标准 vt100+ 终端仿真的地方。 事实上,仿真效果非常好,以至于最终用户甚至可能没有注意到系统处于图形模式。 在此级别,内核对字体和以前通过 SVGATextMode 等实用程序提供的其他功能具有更大的控制权。
现在,所有这些功能都很棒,但可能成为大多数 Linux 用户尝试帧缓冲驱动程序的最主要原因是启动徽标。 是的,现在您终于可以在每次打开计算机时拥有 Tux 带着啤酒的可爱小图片了。
在新系统下,存在的安全问题不如旧系统下那么多。 编写图形应用程序的程序员不需要像他们的传统同行那样小心,因为他们受到内核用户级安全性的保护。 系统管理员也将减少要跟踪的“setuid root”应用程序,从而使他们的安全审计更容易。 相比之下,内核中会有更多可能出错的代码,内核开发人员需要保持新的视频子系统与 Linux 内核的其余部分一样无错误。
如果新的内核子系统要得到广泛使用,我最喜欢的功能可以用两个词来概括:跨平台兼容性。 简而言之,为使用帧缓冲而编写的应用程序将立即移植到所有 Linux 平台。 这与当前的 SVGALib 系统形成直接对比,后者确实具有一定的跨平台兼容性——但仅限于具有类似 VGA 硬件的系统。 从理论上讲,这将使在多个 Linux 架构上编译任何图形应用程序像今天使用 ncurses 编译应用程序一样容易。
但是请记住,此论点不适用于已经跨平台的 X 应用程序。 相反,这种级别的兼容性将在较低级别上对 X 有所帮助。
在内核级别为视频硬件提供单个抽象级别的另一个优势是 X 服务器。 与需要专注于一类视频卡的特定功能的旧 X 服务器不同,了解帧缓冲的 X 服务器可以完全专注于网络和其他 X 方面,同时允许内核处理视频细节。 在我理想的世界中,这将使开发人员有更多时间关注 X 问题而不是视频问题。 如果开发人员仍然有兴趣开发视频代码,他或她总是可以查看内核以寻找可以做的事情。
用于帧缓冲的 X 服务器已经作为 Xfree86-FBDev 提供,并且已随某些发行版一起发布。
新内核驱动程序系统的最大缺点之一,也是最受关注的缺点之一,是稳定性问题。 这些新的帧缓冲会影响现代 Linux 的出色正常运行时间吗? 答案很简单,不会。 Linux 最光荣的事情之一是您通常永远不会被迫做您不想做的事情,并且禁用帧缓冲就像重新编译一样容易(如果发行版甚至默认附带它——我对此深表怀疑)。
我认为 Linux 开发人员达到了比其他一些软件开发人员更高的标准。 (这可能解释了为什么我从未在内核中获得超过微小的东西。)即使在最坏的情况下,猖獗的内核模块也只比猖獗的“setuid root”X 服务器稍微危险一些。 人们每天都在接受这种风险。
新的驱动程序系统比其旧版本支持的硬件更少。 此外,受支持的硬件通常处于次优或非加速位置。 与 XFree 以及在较小程度上与 SVGAlib 相比,这是一个数量级更少的支持。 今天的视频子系统很像昨天的声音子系统,即它支持的卡很少。 随着时间和耐心,开发人员无疑将使这个新系统尽可能健壮。
此外,帧缓冲并非旨在成为加速架构的通用基础。 虽然将来很可能会提供更好的加速,但我们可能必须等到它普遍可用。 或者,GGI 项目(通用图形接口,网址为 http://www.ggi-project.org/)或某些组织很可能会提出并实施解决这种情况的变通方案。 再次强调,由于系统的新颖性,并非所有答案都是立竿见影的。
Red Hat 5.2(我在家和工作中使用)已经包含对帧缓冲 X 服务器 FBDev 的支持。 如果您正在试验 Linux 2.2 的此功能并且拥有 Red Hat,这将为您节省下载/编译周期。 不幸的是,目前还没有简单的方法来配置此设备; 我建议查阅文档。 Red Hat 6.0 可能会包含此功能或使其更易于使用。
Joseph Pranevich (jpranevich@lycos.com) 是一位狂热的 Linux 爱好者,在不为 Lycos 工作时,他喜欢写作(各种类型)并参与许多开源项目。