11. 使用多显示器帧缓冲

本文档的这一部分由 Frederick A. Niles 慷慨捐赠,他保留本节 HOWTO 中包含的所有信息的权利。

11.1. 简介

本文档的主要目的是帮助您开始运行 Linux 的双显示器配置。虽然这个过程非常直接,但在这个过程中可能会出现许多错误。

我重点介绍的例子是在第二个显示器上运行 X 服务器。我发现这很不错,因为您通常可以找到人们因为无法使用而赠送的旧的 19 英寸到 21 英寸的固定频率显示器。这样,您可以从一个小的多频显示器启动,然后在漂亮的大显示器上使用 X。

请理解,双显示器支持目前正在开发中,因此此信息变化迅速。本文档中的任何内容都可能在您阅读本文时已过时或完全不正确。

** 警告 ** 本文档是在 XFree86 4.0 发布之前编写的。如果您正在阅读本文,并且 XFree86 4.0 已经发布,那么许多事情可能已经发生了变化。如果可以找到,请尝试获取本文档的更新版本。

11.2. 反馈

非常欢迎对本文档提出反馈。没有您的提交和投入,本文档将不会存在。因此,请将您的补充、评论和批评发布到.

11.3. 贡献者

以下人员为本迷你 HOWTO 做出贡献。

11.4. 标准免责声明

对于本文档的内容,不承担任何责任。使用本文档中的概念、示例和其他内容,风险自负。由于这是本文档的新版本,可能存在错误和不准确之处,可能会对您的系统造成损害。请谨慎操作,尽管这种情况极不可能发生,但我对此不承担任何责任。

11.5. 版权信息

本文档的这一节版权归 Frederick Niles 1999 年所有,并根据以下条款分发

11.6. 支持哪些硬件?

大多数显卡都假定它们将是系统中唯一的显卡,并且永久设置为主显示适配器的寻址方式。但也有一些例外。

注意:只有第二个适配器必须是上述之一。

11.7. 商业支持

本迷你 HOWTO 主要关注自由软件。但是,也有商业 X 服务器提供多显示器支持。其中包括 Metro Link (www.metrolink.com) 的 Metro-X 和 Xi Graphics (www.xig.com) 的 Accelerated-X。

11.8. 获取所有内容

您需要以下补丁和程序

11.9. 开始入门

您需要做的第一件事是用 "fbaddon" 补丁修补 Linux 源代码副本。然后您需要配置内核并启用帧缓冲支持。如果您有 Matrox 显卡,请启用 Matrox 统一加速驱动程序支持以及您拥有的特定显卡类型。不要启用 VESA 帧缓冲支持。它可能会导致冲突。务必启用多显示器支持(显然)。构建内核并重新启动。

现在您需要安装 "fbset" 程序,并仔细阅读所有关于如何调整设置的文档。一旦您确定了设置,强烈建议使用 "/etc/fb.modes" 文件。fbset 程序包含一个 Perl 脚本,用于将您的 XF86Config 文件转换为 fb.modes 设置。我已在附录 A 和 B 中包含了我的 octave/Borne shell 脚本,用于转换您的 XF86Config 文件。

您需要熟练地在一个显示器上使用帧缓冲设备,了解您的设置可能出现的与多显示器支持无关的任何问题。这可以节省以后大量的挠头苦思。

我将重点解释如何在第二个显示器上运行 X,因为执行大多数其他配置只是该过程的显而易见的子集。

11.9.1. 移动控制台...

编译 "con2fb" 程序。如果您在没有任何参数的情况下运行它,您将收到以下使用消息:“usage: con2fb fbdev console”。

因此,一个示例命令是 "con2fb /dev/fb1 /dev/tty6",将虚拟控制台编号 6 移动到第二个显示器。使用 Ctrl-Alt-F6 移动到该控制台,并查看它是否确实显示在第二个显示器上。

11.9.2. 使用 "" 调整第二个显示器上的设置

仅在运行 "fbset" 命令的显示器上设置 "fbset" 设置。因此,您必须小心在第二个显示器上使用 "-fb" 标志。特别是,如果您什么都不做,您可能至少需要将虚拟垂直分辨率设置为您的实际垂直分辨率。

例如 "fbset -fb /dev/fb1 -vyres 600"

这将严重降低文本模式的速度,但没有它,X 会很糟糕。

11.9.3. 设置 X 以支持帧缓冲。

framebuffer.txt 文件比我能解释得更好,但这里有两个重点。

确保将 "X" 的链接设置为指向 "XF86_FBDev"。

接下来,您需要在 XF86Config 文件中为帧缓冲设备添加一个 Monitor section(显示器节)。这是一个例子

# 帧缓冲服务器 Section "Screen" Driver "fbdev" Device "Millennium" Monitor "NEC MultiSync 5FGp" Subsection "Display" Depth 8 Modes "default" ViewPort 0 0 EndSubsection Subsection "Display" Depth 16 Modes "default" ViewPort 0 0 EndSubsection Subsection "Display" Depth 24 Modes "default" ViewPort 0 0 EndSubsection Subsection "Display" Depth 32 Modes "default" ViewPort 0 0 EndSubsection EndSection

使用 "default" 模式,因为我认为任何其他模式都无法与 Matrox 帧缓冲一起工作。

11.9.4. 尝试在第二个显示器上启动 X 服务器

将环境变量 FRAMEBUFFER 设置为第二个帧缓冲。

"export FRAMEBUFFER=/dev/fb1" 或 "setenv FRAMEBUFFER /dev/fb1"

您需要启动 X 服务器,使其既匹配选定的颜色深度,又显示在您从中启动 X 服务器的同一显示器上。

例如 "startx -- :0 -bpp 16 vt06"

此示例将在虚拟控制台 6 上以 16 位颜色启动 "zeroth" X 服务器。为另一个帧缓冲启动另一个 X 服务器时使用 ":1" 将允许您运行两个 X 服务器。

11.10. 总结

在第二个显示器上运行 X 服务器所涉及的步骤可以总结如下

然后每次重新启动时

您可以每次重新启动时通过 shell 别名自动执行此操作。它必须是别名而不是 shell 脚本,因为它需要检测当前的控制台编号。这是我的 csh 别名,用于在第二个固定频率显示器上启动 X

alias startxfb = " setenv FRAMEBUFFER /dev/fb\!*; # 将环境变量设置为命令参数。 con2fb $FRAMEBUFFER /dev/$tty; # 将帧缓冲移动到当前 tty。 fbset -fb $FRAMEBUFFER 1280x1024@62; # 来自 /etc/fb.modes 的常用设置 startx -- :\!* -bpp 16 vt0`echo $tty | cut -dy f 2`' # 此 tty 上的 X。 "

在我的 .cshrc 文件中,这些都在同一行上,没有注释,但在这里更容易阅读,添加了换行符和注释。我只给出帧缓冲的编号作为参数,它就会立即启动。

我不确定如何在 bash 中执行相同的别名。我不知道如何确定当前的 tty 或在 bash 中获取别名的参数。如果有人告诉我,我将在此处插入它。但是,您可以使用 "tty" 命令获取当前 VT 的名称,并为每个 X 服务器制作两个单独的别名。

11.11. 其他注意事项和问题

11.11.1. 使 ""(即 / )工作

我还没有找到一种方法可以在双显示器配置下以 init level 5 启动(并且实际上在第二个显示器或两者上都有服务器)。虽然在 gdm/xdm Xservers 文件中添加一行似乎很容易,但您必须从同一帧缓冲启动 X 服务器的约束阻止了显而易见的解决方案起作用。如果有人找到了方法,请给我发电子邮件,我会将其添加到此处。

11.11.2. 使用 "" 程序

有一个名为 x2x 的漂亮小程序,当您到达屏幕边缘时,它会为您切换 X 服务器。此程序的最后一个已知主页是:http://ftp.digital.com/pub/DEC/SRC/x2x/ 它也是一个可选的 Debian 软件包。我还没有尝试过,但一些用户报告说成功了。

11.11.3. 其他有用的命令

这些是现有的 Linux 命令,在处理多显示器配置(尤其是在编写脚本时)时值得记住。

  • "chvt" 将允许您在虚拟终端之间切换。

  • "openvt" 在新的虚拟终端 (VT) 上启动程序。

  • "tty" 将报告当前终端的名称。

11.12. 附录 A. Octave "" 脚本

(注意 bpp 设置)

#!/usr/bin/octave -q bpp = 16; DCF = sscanf(argv(1,:), "%f"); HR = sscanf(argv(2,:), "%f"); SH1 = sscanf(argv(3,:), "%f"); SH2 = sscanf(argv(4,:), "%f"); HFL = sscanf(argv(5,:), "%f"); VR = sscanf(argv(6,:), "%f"); SV1 = sscanf(argv(7,:), "%f"); SV2 = sscanf(argv(8,:), "%f"); VFL = sscanf(argv(9,:), "%f"); pixclock = 1000000 / DCF; left_margin = HFL - SH2; right_margin = SH1 - HR; hsync_len = SH2 - SH1; # 3) vertical timings: upper_margin = VFL - SV2; lower_margin = SV1 - VR; vsync_len = SV2 - SV1; RR = DCF / (HFL * VFL) *1e6; HSF = DCF / HFL * 1e3; printf("mode \"%dx%d\"\n",HR,VR); printf(" # D: %3.2f MHz, H: %3.2f kHz, V: %2.2f Hz\n", DCF, HSF, RR); printf(" geometry %d %d %d %d %d\n", HR, VR, HR, VR, bpp); printf(" timings %d %d %d %d %d %d %d\n", ... pixclock, left_margin, right_margin, ... upper_margin, lower_margin, ... hsync_len, vsync_len); printf("endmode\n");

11.13. 附录 B. Bourne Shell "" 脚本

(这调用 octave 脚本 "cvtmode")

#!/bin/sh # Shell 脚本,用于将 XF86Config 文件转换为 fb.modes 文件。 # 使用 octave 脚本 cvtmode.m if [ -z $1 ]; then FILE=/etc/X11/XF86Config else FILE=$1 fi i=1 LEN=`grep Modeline $FILE | wc -l` while expr $i \< $LEN > /dev/null ; do CURLINE=`grep Modeline $FILE | cut -d'"' -f 3-20 | head -$i | tail -1 ` ./cvtmode.m $CURLINE echo " " i=`expr $i + 1` done