Linux-GGI 项目
在本文中,我们将解释 Linux-GGI 项目的意图和目标,以及 GGI 程序员使用的基本概念,这些概念允许快速、易于使用地访问图形服务,从应用程序中隐藏硬件级别的问题,并为 Linux 下的多个显示器引入可扩展的支持。Linux-GGI 项目旨在为 Linux 建立一个通用图形界面,以便在 Linux 操作系统下轻松使用图形硬件和输入设备。诸如 X 或 OpenGL 等现有解决方案和标准确实处理了图形问题,但目前 Linux 下的这些实现存在一些(有时是严重的)缺陷。
控制台切换并非无死锁,因为内核会要求用户模式应用程序允许切换,这会在安全性方面造成问题。由于任何用户模式应用程序都可以锁定控制台,因此内核必须依赖应用程序来允许用户发起的切换。对于独立机器,如果控制台在没有切换的应用程序中锁定,则必须重新启动系统。
安全关注键 (SAK) 可以终止与当前虚拟控制台关联的所有进程,这可能有助于解决上述问题,但对于图形应用程序,机器可能仍然保持锁定状态,因为内核无法正确重置控制台——毕竟,它不知道存在哪些视频硬件。
任何在低级别访问图形硬件的应用程序都必须是可信的,因为它需要以 root 身份运行才能获得对图形硬件的访问权限。当发起控制台切换时,内核依赖应用程序来恢复硬件状态。对于出于其他原因需要超级用户权限的 X 服务器来说,依赖应用程序可能还可以,但我们大多数人都不想信任一个仅以二进制形式提供给我们的游戏。
可以使用当前方法访问输入硬件(例如鼠标或操纵杆),但它不能在多个虚拟控制台和使用它的应用程序之间轻松共享。
没有干净的方法可以使用多个键盘和显示器组合。您可能会认为这在 PC 硬件上无论如何都是不可能的;但事实上,使用当前现有的硬件,有办法拥有多头 PC,并且即将推出的 USB 外围总线可能允许多个键盘等。此外,其他架构确实支持多个显示器,如果 Linux 也支持,这将是使用 Linux 进行 CAD/CAE 技术等应用程序的一个很好的理由。
游戏无法以最大性能使用现有硬件,因为它们要么必须使用 X,这会引入很大的开销(从游戏程序员的角度来看),和/或直接访问硬件,这需要为它们运行的每种硬件类型单独的驱动程序。
GGI 以一种干净且可扩展的方式解决了所有这些问题以及更多问题。(GGI 并不希望成为这些现有标准的替代品,也不希望完全在内核内部实现其图形服务。)现在,让我们看一下 GGI 的概念——其中一些概念已经实现并显示了它们的可用性。
GGI 硬件驱动程序由一个内核空间模块(称为内核图形界面 (KGI))和一个用户空间库(称为 libGGI)组成。GGI 的 KGI 部分将由一个显示管理器组成,该管理器负责访问多个视频卡并在较旧的硬件上执行 MMU 支持的页面翻转。这种方法允许在可能的情况下从用户空间非常快速地访问帧缓冲区。(这项技术已经得到证实——用于 DJPGG 的 GO32 图形库,用于 DOS 的 GNU-C 编译器,使用了这种方法,并且在较旧的硬件上具有惊人的快速图形支持。)如果这种内存映射访问方法可以在 GGI 中使用,那么当应用程序直接读取或写入像素缓冲区时,性能不会有损失。
系统中每种类型的视频卡都有自己的驱动程序,这是一个简单的可加载模块,它注册了该卡可以寻址的尽可能多的显示器。(存在支持两个显示器或一个显示器和一个电视屏幕的视频卡。)驱动程序模块为系统提供了访问帧缓冲区所需的信息,以及访问特殊的加速功能、设置特定视频模式和硬件限制(例如,显卡、显示器和显示系统的任何其他部分)所需的信息。该模块可以从单个源文件获得,也可以使用预编译的子驱动程序链接,用于每个图形硬件子系统(ramdac、显示器、时钟芯片、芯片组、加速引擎)。最后一个选项是最受欢迎的方法,因为它允许非常容易地添加对新卡的支持,因为只需要实现和测试尚未支持的硬件的子驱动程序。(其他的已经在使用中,或者那里的错误修复将改进所有使用它们的驱动程序。)该方案已被用于派生对许多基于 S3 加速器的卡的支持,并且已被证明非常高效且易于使用。它还允许对多个显卡进行高效的同步开发。要链接在一起的子驱动程序现在在配置时选择,但也可以在自动检测后或根据数据库(尚未构建)选择。请注意,子驱动程序不需要采用源代码形式;因此,预编译的子驱动程序目标文件可以在安装期间链接在一起。
由于每个子驱动程序都确切地知道硬件,因此它可以防止显示硬件因配置错误而损坏,并就硬件的最佳使用提出建议。例如,当前实现具有用于固定和多同步显示器的驱动程序,这些驱动程序允许即时计算任何分辨率的最佳时序,而无需任何进一步的配置。当然,也可能完全由用户配置驱动程序。简而言之,除了硬件级别代码之外,子系统驱动程序还提供尽可能多的关于硬件的信息。这样,内核将有足够的方法来初始化卡,在应用程序终止时重置控制台和视频模式,并充分利用硬件。KGI 管理器将允许单个内核映像在所有硬件上支持 GGI,因为任何硬件特定的代码都在可加载模块中,并且只有公共服务(例如内存映射代码)是从内核提供的。KGI 管理器还将为几乎任何可以想象的输入设备类型提供数据结构和支持。
用户空间库(称为 libGGI)将为应用程序实现一个抽象编程接口。它使用特殊的设备文件和标准文件操作来与内核部分交互。应用程序应使用此接口(或基于它的应用程序提供的 API)以获得最大性能;但是,可以构建其他 API 来直接访问特殊文件。请理解,在这种情况下,就图形访问而言,X 服务器将只是一个普通的应用程序。由于 X 被认为是图形服务的主要客户,因此 API 将根据 X 协议定义进行设计,并将实现 X 服务器所需的一组低级绘图例程。该库将尽可能使用加速功能,并模拟硬件无法有效支持的功能。未来一代图形硬件的一个重要特性是 3D 加速,它很容易符合 GGI 的观点。我们计划提供基于 MESA 的 3D 功能支持,MESA 类似于 OpenGL,并确保与 Linux 以外的其他平台的兼容性。
处理图形的另一个问题是游戏编程,因为游戏需要尽可能高的性能。它们还需要视频硬件的特殊支持,以生成无闪烁的动画或逼真的图像。当前的方法无法以合理的方式支持这种需求,因为它们无法获得内核的帮助(例如,使用回扫中断)。GGI 可以轻松提供这种支持,并为所有应用程序提供最大的硬件支持。
有很多与计算机交互的方式——键盘、鼠标,甚至是网络套装。所有这些方法都有特殊的协议来报告用户操作,甚至需要特殊的硬件才能访问。GGI 将允许支持任何类型的输入,而无需为每个新设备重新编译内核,从而实现灵活性和轻松配置。这种支持是通过为每个设备或设备类配备一个可加载模块来实现的。就像视频卡驱动程序一样,任何输入设备驱动程序都将注册抽象输入设备,这些设备将用户操作转换为事件。
例如,应用程序可能会查询已注册的设备并选择它想要接收的事件,以便游戏程序可以根据环境默认为使用操纵杆或键盘输入。安装游戏或 X 服务器不需要任何进一步的配置,只需将二进制文件复制到其目标目录并启动它即可。请注意,这种方法还将大大减少维护几台配置不同的机器所需的工作量,因为应用程序二进制文件对于所有机器都是相同的,并且可以通过网络文件系统共享。只有要加载的 GGI 模块会因机器而异。
GGI 将控制台定义为一对——一个显示器和一个(强制性的)字符输入设备。可选地,可以存在其他输入设备,例如连接到控制台的指点设备或控制器。显示器能够提供字母数字数据或图形,而字符设备提供字符输入(顾名思义)。我们使用这些模糊的术语,因为显示器实际上可能是显示器以外的东西,例如,盲文行或其他帮助残疾人或伤障人士使用计算机的设备。类似地,输入可能是键盘或语音识别程序或硬件——几乎任何你能想象到的东西。但是,字符输入设备是强制性的,因为它专注于一个且仅一个虚拟控制台,该控制台显示在加载模块注册的显示器之一上。任何其他设备都与键盘之一相关联,并且任何用户活动都会报告给在聚焦控制台上运行的应用程序。因此,不仅可以拥有多个虚拟控制台,而且(与多个显示器结合使用)还可以拥有多个真实控制台。
如果用户想要在两个虚拟控制台之间切换,键盘驱动程序将告诉 KGI 管理器将指定的虚拟控制台带到分配给它的显示器上,然后将任何键盘、指针和控制器事件报告给应用程序。虚拟化产生的一个问题是,访问加速功能的应用程序可能首先必须终止当前命令,或者即使应用程序进入后台模式也需要保留帧缓冲区。GGI 将有效地向应用程序隐藏此操作。应用程序可以分为以下几类,并给出示例
应用程序可以随时重绘其屏幕,而不会产生明显的开销,例如,X 服务器。
当提供备份缓冲区以防帧缓冲区需要在任何时候都可访问时,应用程序的编程可以大大简化,例如,光线追踪器或任何其他需要进行大量计算来绘制图像的程序。此备份还允许在后台模式下运行应用程序,同时继续绘制到其帧缓冲区。
如果应用程序不在前台模式,则可以跳过输出或简单地休眠,从而显着降低系统负载,例如,游戏或软件视频解码器。SVGALIB 以这种方式工作。
第一类和第三类很容易虚拟化——它们只需在切换到前台模式时重绘其缓冲区,因此,当切换到后台模式时,屏幕内容将被丢弃,并且绘图请求将被忽略。唯一困难的类别是第二类。但是,由于内核知道硬件的确切状态,它可以告诉用户空间守护程序分配足够的内存,将帧缓冲区保存在那里,重定向应用程序的内存映射,并告诉库使用针对内存映射缓冲区的优化绘图方法,而不是加速绘图功能。
GGI 计划为 Linux 操作系统添加强大的图形硬件支持。与任何硬件驱动程序一样,它需要有一个内核段,该内核段应保持在最低限度(当前模块的大小约为 30K,并且不应超过 80K)。如果被 Linux 社区接受,GGI 可以提供一种处理多个显示器和输入硬件的干净方法,以及一个与架构无关的编程接口,该接口将在任何平台上提供良好的性能。此外,如果硬件制造商愿意,它将允许他们为其硬件提供优化的驱动程序。在开发过程中,已经并将继续非常注意尽可能地隔离机器或硬件相关的代码,以提供良好的可移植性。
由于 GGI 仍在开发中,因此一些功能尚未实现,但第一个实现证明我们的概念能够轻松访问视频硬件并解决本文中提到的所有问题。目前正在开发的是对多个显示器和 libGGI 的支持。当然,向内核引入一个新概念来访问视频硬件将导致几个(非 X)应用程序不兼容,但另一方面,添加这个概念将简化 Linux 的配置,并为游戏程序员打开新的前景,操作系统和图形支持将允许在任何系统上实现最大性能。
Andreas Beck (becka@sunserver1.rz.uni-duesseldorf.de) 在德国杜塞尔多夫大学学习物理学,并发起了 GGI 项目。他开发了 GGI 的内存映射代码,致力于库的实现,并为所使用的概念做出了重大贡献。
Steffen Seeger (seeger@physik.tu-chemnitz.de) 也在开姆尼茨-茨维考技术大学学习物理学。他编写了大部分 S3 驱动程序代码,并为控制台概念和内核驱动程序做出了重大贡献。