Linux工作原理14桌面和打印简介

  • Linux工作原理14桌面和打印简介已关闭评论
  • 26 次浏览
  • A+
所属分类:linux技术
摘要

本章简要介绍了典型 Linux 桌面系统中的组件。在 Linux 系统的各种软件中,桌面是最狂野、最丰富多彩的领域之一,因为有如此众多的环境和应用程序可供选择,而且大多数发行版都能让你比较容易地试用它们。


14桌面和打印简介

本章简要介绍了典型 Linux 桌面系统中的组件。在 Linux 系统的各种软件中,桌面是最狂野、最丰富多彩的领域之一,因为有如此众多的环境和应用程序可供选择,而且大多数发行版都能让你比较容易地试用它们。

与 Linux 系统的其他部分(如存储和网络)不同,创建桌面结构并不涉及庞大的层次结构。相反,每个组件都执行特定的任务,并在必要时与其他组件通信。有些组件确实共享共同的构建模块(尤其是图形工具包库),你可以将其视为简单的抽象层,但这也是最深的层次。

本章将从总体上对桌面组件进行高层次的讨论,但我们将更详细地探讨两部分内容:大多数桌面背后的核心基础架构和 D-Bus(一种用于系统许多部分的进程间通信服务)。我们的讨论和示例将仅限于一些诊断工具,虽然这些工具在日常使用中用处不大(大多数图形用户界面不需要输入 shell 命令就能与之交互),但它们能帮助你了解系统的基本机制,或许还能给你带来一些娱乐。我们还将快速了解一下打印,因为桌面工作站通常共用一台打印机。

14.1 桌面组件

Linux 桌面配置具有极大的灵活性。Linux 用户体验的大部分内容(桌面的 “外观和感觉”)都来自应用程序或应用程序的构建模块。如果你不喜欢某个特定的应用程序,通常可以找到替代品。如果你想找的东西不存在,你也可以自己编写。Linux 开发人员往往对桌面的运行方式有各种各样的偏好,这就给了你很多选择。

为了协同工作,所有应用程序都需要有一些共同点。在撰写本文时,Linux 桌面的核心正处于过渡状态。从一开始到最近,Linux 桌面一直使用 X(X Window System,又称 Xorg,以其维护组织命名)。不过,现在这种情况正在发生变化;许多发行版已经过渡到基于 Wayland 协议的软件集,以构建窗口系统。

要了解底层技术的这一变化的驱动因素,让我们回过头来看看一些图形基础知识。

14.1.1 帧缓冲区

任何图形显示机制的底层都是帧缓冲器,它是图形硬件读取并传输到屏幕以供显示的内存块。帧缓冲区中的几个字节代表显示屏上的每个像素,因此,如果要改变显示效果,就需要向帧缓冲区内存写入新的值。

窗口系统必须解决的一个问题是如何管理向帧缓冲区的写入。在任何现代系统中,窗口(或窗口集)都属于单独的进程,独立完成所有图形更新。因此,如果允许用户移动窗口并将一些窗口重叠在另一些窗口之上,那么应用程序如何知道在哪里绘制图形,又如何确保一个应用程序不会覆盖其他窗口的图形?

14.1.2 X 窗口系统

X 窗口系统采用的方法是建立一个服务器(称为 X 服务器),作为桌面的 “内核”,管理从渲染窗口、配置显示器到处理键盘和鼠标等设备的输入等一切事务。X 服务器不会规定任何操作或显示方式。相反,X 客户端程序负责处理用户界面。基本的 X 客户端程序(如终端窗口和网络浏览器)会与 X 服务器建立连接,并要求绘制窗口。作为回应,X 服务器会计算窗口的位置和客户端图形的渲染位置,并承担一定的责任将图形渲染到帧缓冲区。X 服务器还会在适当的时候向客户端传送输入信息。

由于 X 服务器充当了所有工作的中介,因此它可能会成为一个重要的瓶颈。此外,X 服务器还包含大量不再使用的功能,而且它的历史也相当悠久,可以追溯到 20 世纪 80 年代。但不知为何,它却能灵活地容纳许多新功能,从而延长了它的使用寿命。本章稍后我们将介绍如何与 X 窗口系统交互的基础知识。

Linux工作原理14桌面和打印简介

14.1.3 Wayland

与 X 不同,Wayland 在设计上非常分散。它没有大型显示服务器来管理多个图形客户端的帧缓冲区,也没有中央机构来渲染图形。取而代之的是,每个客户端都会为自己的窗口获取自己的内存缓冲区(可将其视为子帧缓冲区),然后由一个名为合成器的软件将所有客户端的缓冲区合并成必要的形式,再复制到屏幕的帧缓冲区。由于这项任务通常有硬件支持,因此合成器的效率相当高。

在某些方面,Wayland 的图形模型与大多数 X 客户端多年来的做法并无太大区别。大多数客户端不会从 X 服务器获取任何帮助,而是将自己的所有数据渲染为位图,然后将位图发送到 X 服务器。为了在某种程度上承认这一点,X 的合成扩展已经使用了好几年。

为了将输入引导到正确的应用程序,大多数 Wayland 设置和许多 X 服务器都使用名为 libinput 的库来标准化客户端事件。Wayland 协议并不需要这个库,但在桌面系统中,它几乎是通用的。我们将在第 14.3.2 节讨论 libinput。

Linux工作原理14桌面和打印简介

14.1.4 窗口管理器

X 和 Wayland 系统的一个主要区别在于窗口管理器,它是决定如何在屏幕上排列窗口的软件,也是用户体验的核心。在 X 系统中,窗口管理器是一个客户端,充当服务器的助手;它绘制窗口的装饰(如标题栏和关闭按钮),处理这些装饰的输入事件,并告诉服务器在哪里移动窗口。

不过,在 Wayland 中,窗口管理器或多或少就是服务器。它负责将所有客户端窗口缓冲区合成到显示帧缓冲区中,并处理输入设备事件的通道。因此,它需要比 X 中的窗口管理器做更多的工作,但其中大部分代码可以在窗口管理器实现之间通用。

两种系统中都有许多窗口管理器实现,但 X 系统由于历史悠久,窗口管理器实现要多得多。不过,大多数流行的窗口管理器,如 GNOME 中的 Mutter 和 KDE 中的 Kwin,都已扩展至支持 Wayland 合成。无论底层技术如何,都不可能有一个标准的 Linux 窗口管理器;因为用户的口味和需求多种多样,而且不断变化,所以新的窗口管理器层出不穷。

14.1.5 工具包

桌面应用程序包含某些通用元素,如按钮和菜单,这些元素被称为部件。为了加快开发速度并提供通用的外观,程序员会使用图形工具包来提供这些元素。在 Windows 或 macOS 等操作系统上,供应商会提供一个通用工具包,大多数程序员都会使用该工具包。在 Linux 上,GTK+ 工具包是最常见的工具包之一,但你也会经常看到基于 Qt 框架和其他框架构建的 widget。

工具包通常由共享库和支持文件(如图像和主题信息)组成。

14.1.6 桌面环境

虽然工具包为用户提供了统一的外观,但桌面的某些细节需要不同应用程序之间的合作。例如,一个应用程序可能希望与另一个应用程序共享数据或更新桌面上的公共通知栏。为了满足这些需求,工具包和其他库被捆绑成更大的软件包,称为桌面环境。GNOME、KDE 和 Xfce 是一些常见的 Linux 桌面环境。

工具包是大多数桌面环境的核心,但要创建一个统一的桌面,环境还必须包含大量的支持文件,如图标和配置,这些文件组成了主题。所有这些都与描述设计惯例的文件结合在一起,例如应用程序菜单和标题应如何显示,以及应用程序应如何对某些系统事件作出反应。

14.1.7 应用程序

位于桌面顶部的是应用程序,如网络浏览器和终端窗口。X 应用程序既有简单的(如古老的 xclock 程序),也有复杂的(如 Chrome 浏览器和 LibreOffice 套件)。这些应用程序通常是独立运行的,但它们经常使用进程间通信来感知相关事件。例如,当您附加新的存储设备或收到新的电子邮件或即时消息时,应用程序就会表示出兴趣。这种通信通常通过第 14.5 节所述的 D-Bus 进行。

14.2 运行的是 Wayland 还是 X?

在开始实践讨论时,您需要先确定自己使用的是哪种图形系统。只需打开 shell,查看 $WAYLAND_DISPLAY 环境变量的值。如果值是 wayland-0 这样的值,说明你运行的是 Wayland。如果没有设置,则运行的是 X 系统(很可能;也有例外,但这种测试不太可能遇到)。

这两种系统并不相互排斥。如果你的系统使用 Wayland,那么它很可能也在运行 X 兼容服务器。也可以在 X 内启动 Wayland 合成器,但这可能会有点奇怪(稍后详述)。

14.3 近距离观察 Wayland

我们将从 Wayland 开始,因为它是新兴的标准,目前在许多发行版中被默认使用。遗憾的是,部分原因是它的设计和使用时间尚短,因此没有像 X 那样多的工具来深入研究 Wayland。

首先,让我们来谈谈 Wayland 是什么和不是什么。Wayland 这个名字指的是合成窗口管理器和图形客户端程序之间的通信协议。如果你去寻找一个大型的 Wayland 核心软件包,你是找不到的,但你会找到大多数客户端用来与协议对话的 Wayland 库(至少目前是这样)。

此外,还有一个名为 Weston 的参考合成窗口管理器,以及一些相关的客户端和实用工具。参考的意思是,Weston 包含合成器的必要功能,但并不适合大众使用,因为它只有一个简陋的界面。这样做的目的是让合成窗口管理器的开发人员可以参考 Weston 源代码,了解如何正确实现关键功能。

14.3.1 合成窗口管理器

听起来很奇怪,您可能不知道自己实际运行的是哪个 Wayland 合成窗口管理器。你也许能从界面的信息选项中找到名称,但没有固定的查找位置。不过,通过追踪合成器与客户端通信时使用的 Unix 域套接字,你几乎总能找到正在运行的合成器进程。套接字是 WAYLAND_DISPLAY 环境变量中的显示名称,通常是 wayland-0,一般位于 /run/user/,其中 是你的用户 ID(如果不是,请查看 $XDG_RUNTIME_DIR 环境变量)。以根用户身份运行ss命令,可以找到监听该套接字的进程,但输出结果看起来会有点疯狂:

# ss -xlp | grep wayland- u_str LISTEN 0 128 /run/user/1000/wayland-0 755881 * 0 users:((“gnome-shell”,pid=1522,fd=30),(“gnome-shell”,pid=1522,fd=28)) 

不过,你只需仔细查看,就会发现编译器进程是 gnome-shell,PID 1522。不幸的是,这里还存在另一层间接关系;GNOME shell 是 Mutter 的一个插件,而 Mutter 是 GNOME 桌面环境中使用的合成窗口管理器。(在这里,称 GNOME shell 为插件只是一种花哨的说法,即它将 Mutter 作为一个库来调用)。

Wayland 系统中比较特别的一点是绘制窗口装饰(如标题栏)的机制。在 X 系统中,窗口管理器负责绘制所有这些装饰,但在 Wayland 的最初实现中,这都是由客户端应用程序完成的,这有时会导致窗口在同一屏幕上出现多种不同的装饰。现在,协议中有一部分称为 XDG-Decoration,允许客户端与窗口管理器协商,看窗口管理器是否愿意绘制装饰。

在 Wayland 合成器的上下文中,你可以将显示屏视为帧缓冲区所代表的可视空间。如果一台电脑连接了多个显示器,那么一个显示器可以跨越多个显示器。

虽然这种情况很少见,但您可以同时运行多个合成器。一种方法是在不同的虚拟终端上运行合成器。在这种情况下,第一个合成器的显示名称通常设置为 wayland-0,第二个为 wayland-1,以此类推。

你可以使用 weston-info 命令来了解一下你的合成器,它可以显示合成器可用接口的一些特征。不过,除了显示屏和某些输入设备的信息外,您不应对其他信息抱有太多期望。

14.3.2 libinput

为了将键盘等设备的输入从内核传送到客户端,Wayland 合成器需要收集这些输入,并以标准化的形式将其传送到相应的客户端。libinput 库包含从各种 /dev/input 内核设备收集输入并对其进行按摩所需的支持。在 Wayland 中,合成器通常不会原封不动地传递输入事件,而是先将事件翻译成 Wayland 协议,然后再发送给客户端。

通常情况下,像 libinput 这样的东西并不值得大谈特谈,但它自带的一个小工具(也叫 libinput)可以让你检查内核显示的输入设备和事件。

试着用下面的方法查看可用的输入设备(你可能会得到大量输出,所以要做好翻阅的准备):

# libinput list-devices --snip-- Device:           Cypress USB Keyboard Kernel:           /dev/input/event3 Group:            6 Seat:             seat0, default Capabilities:     keyboard  Tap-to-click:     n/a Tap-and-drag:     n/a Tap drag lock:    n/a Left-handed:      n/a --snip-- 

在这个局部视图中,你可以看到设备的类型(键盘)和内核 evdev 设备的位置(/dev/input/event3)。当你监听类似这样的事件时,该设备就会出现:

# libinput debug-events --show-keycodes -event2   DEVICE_ADDED     Power Button                      seat0 default group1  cap:k --snip-- -event5   DEVICE_ADDED     Logitech T400                     seat0 default group5  cap:kp left scroll-nat scroll-button -event3   DEVICE_ADDED     Cypress USB Keyboard              seat0 default group6  cap:k --snip--  event3   KEYBOARD_KEY      +1.04s      KEY_H (35) pressed  event3   KEYBOARD_KEY      +1.10s      KEY_H (35) released  event3   KEYBOARD_KEY      +3.06s      KEY_I (23) pressed  event3   KEYBOARD_KEY      +3.16s      KEY_I (23) released 

运行此命令后,移动鼠标指针并按下一些键。您将获得一些描述这些事件的输出。

请记住,libinput 库只是一个捕获内核事件的系统。因此,它不仅可用于 Wayland,也可用于 X 窗口系统。

14.3.3 Wayland 中的 X 兼容性

在讨论 X 窗口系统的总体情况之前,我们先来探讨一下它与 Wayland 的兼容性。X 应用程序不计其数,如果缺乏对 X 的支持,任何从 X 迁移到 Wayland 的努力都会受到极大阻碍。有两种方法可以同时弥补这一缺陷。

第一种方法是为应用程序添加 Wayland 支持,创建原生的 Wayland 应用程序。大多数在 X 上运行的图形应用程序已经使用了工具包,如 GNOME 和 KDE 中的工具包。由于为这些工具包添加 Wayland 支持的工作已经完成,因此将 X 应用程序制作成原生 Wayland 应用程序并不困难。除了注意对窗口装饰和输入设备配置的支持外,开发人员只需处理应用程序中罕见的 X 库依赖关系即可。对于许多主要应用程序来说,这项工作已经完成。

另一种方法是通过 Wayland 的兼容层运行 X 应用程序。这是通过作为 Wayland 客户端运行的整个 X 服务器来实现的。该服务器被称为 Xwayland,实际上只是 X 客户端下的另一层,默认情况下由大多数合成器启动序列运行。Xwayland 服务器需要翻译输入事件,并单独维护窗口缓冲区。引入另一个这样的中间人总是会稍微拖慢运行速度,但这在大多数情况下都无关紧要。

反过来也不行。你无法以同样的方式在 X 上运行 Wayland 客户端(理论上可以编写这样的系统,但意义不大)。不过,你可以在 X 窗口内运行合成器。例如,如果你正在运行 X,只需在命令行上运行 weston 就能调出合成器。你可以打开终端窗口,并在其中运行任何其他 Wayland 应用程序,如果你正确启动了 Xwayland,甚至可以在合成器中运行 X 客户端。

不过,如果你让合成器继续运行,然后回到正常的 X 会话,你可能会发现某些实用程序并不像你预期的那样工作,它们也可能会显示在合成器窗口中,而你预期它们会显示为 X 窗口。这是因为 GNOME 和 KDE 等系统上的许多应用程序现在都同时支持 X 和 Wayland。它们会首先查找 Wayland 合成器,而在默认情况下,如果未设置 WAYLAND_DISPLAY 环境变量,libwayland 中查找显示的代码会默认为 wayland-0。如果应用程序能找到可用的合成器,它就会使用它。

避免这种情况的最佳方法就是不要在 X 内运行合成器,或与 X 服务器同时运行。

14.4 深入了解 X 窗口系统

与基于 Wayland 的系统相比,X Window System (http://www.x.org/) 在历史上一直非常庞大,基本发行版包括 X 服务器、客户端支持库和客户端。由于 GNOME 和 KDE 等桌面环境的出现,X 的角色随着时间的推移发生了变化,现在更侧重于管理渲染和输入设备的核心服务器,以及简化的客户端库。

X 服务器在系统中很容易识别。它叫 X 或 Xorg。在进程列表中查找它;通常你会看到它在运行,并带有如下选项:

Xorg -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch 

这里显示的 :0 称为 X 显示器,是代表一台或多台显示器的标识符,你可以使用普通键盘和/或鼠标访问这些显示器。通常情况下,显示屏只对应连接到计算机上的一台显示器,但也可以将多台显示器置于同一显示屏下。对于在 X 会话下运行的进程,DISPLAY 环境变量被设置为显示器标识符。

注意:显示器可以进一步细分为多个屏幕,如 :0.0 和 :0.1,但这种情况很少见,因为 RandR 等 X 扩展程序可以将多个显示器合并为一个更大的虚拟屏幕。

在 Linux 中,X 服务器在虚拟终端上运行。在本例中,vt7 参数表明它被告知在 /dev/tty7 上运行(通常情况下,服务器在第一个可用的虚拟终端上启动)。你可以在 Linux 上同时运行多个 X 服务器,方法是在不同的虚拟终端上运行它们,每个服务器都有一个唯一的显示标识符。你可以使用 CTRL-ALT-FN 键或 chvt 命令在服务器之间切换。

14.4.1 显示管理器

通常情况下,我们不会在命令行上启动 X 服务器,因为启动服务器并不会定义在其上运行的任何客户端。如果自行启动服务器,只会得到一个空白屏幕。最常见的启动 X 服务器的方法是使用显示管理器,它是一个启动服务器并在屏幕上显示登录框的程序。登录后,显示管理器会启动一组客户端,如窗口管理器和文件管理器,这样你就可以开始使用机器了。

有许多不同的显示管理器可供选择,如 gdm(用于 GNOME)和 kdm(用于 KDE)。前面 X 服务器调用参数列表中的 lightdm 是一个跨平台显示管理器,用于启动 GNOME 或 KDE 会话。

如果你坚持从虚拟控制台启动 X 会话而不是使用显示管理器,可以运行 startx 或 xinit 命令。不过,由于机制和启动文件不同,您得到的会话可能会非常简单,看起来与显示管理器完全不同。

14.4.2 网络透明

X 的一个特点是网络透明。由于客户端与服务器之间使用的是一种协议,因此可以直接通过网络将客户端连接到另一台机器上运行的服务器,X 服务器在 6000 端口监听 TCP 连接。连接到该端口的客户端可以进行身份验证,然后向服务器发送窗口。

遗憾的是,这种方法通常不提供任何加密,因此并不安全。为了堵住这个漏洞,现在大多数发行版都禁用了 X 服务器的网络监听器(使用服务器的 -nolisten tcp 选项)。不过,如第 10 章所述,通过将 X 服务器的 Unix 域套接字连接到远程计算机上的套接字,你仍然可以使用 SSH 隧道从远程计算机运行 X 客户端。

注意:使用 Wayland 远程运行并不简单,因为客户端有自己的屏幕内存,合成器必须直接访问才能显示。不过,许多新兴系统,如 RDP(远程桌面协议),可以与合成器配合使用,提供远程功能。

14.4.3 探索 X 客户端的方法

虽然人们通常不会想到通过命令行来使用图形用户界面,但有几种实用程序可以让你探索 X 窗口系统的各个部分。特别是,你可以在客户端运行时对其进行检查。

最简单的工具之一是 xwininfo。在不带任何参数的情况下运行时,它会要求你点击一个窗口:

$ xwininfo  xwininfo: Please select the window about which you           would like information by clicking the           mouse in that window. 

点击之后:

xwininfo: Window id: 0x5400024 "xterm"    Absolute upper-left X:  1075   Absolute upper-left Y:  594 --snip-- 

注意这里的窗口 ID。X 服务器和窗口管理器使用此标识符来跟踪窗口。要获取所有窗口 ID 和客户端的列表,请使用 xlsclients -l 命令。

14.4.4 X 事件

X 客户端通过事件系统获取输入和其他有关服务器状态的信息。X 事件的工作方式与其他异步进程间通信事件(如 udev 事件和 D-Bus 事件)类似。X 服务器从输入设备等来源接收信息,然后将输入作为事件重新分配给任何感兴趣的 X 客户端。

你可以通过 xev 命令对事件进行实验。运行该命令会打开一个新窗口,你可以将鼠标移至其中,单击并输入。在此过程中,xev 会生成输出,描述它从服务器接收到的 X 事件。例如,下面是鼠标移动的输出示例:

$ xev --snip-- MotionNotify event, serial 36, synthetic NO, window 0x6800001,     root 0xbb, subw 0x0, time 43937883, (47,174), root:(1692,486),     state 0x0, is_hint 0, same_screen YES  MotionNotify event, serial 36, synthetic NO, window 0x6800001,     root 0xbb, subw 0x0, time 43937891, (43,177), root:(1688,489),     state 0x0, is_hint 0, same_screen YES 

请注意括号中的坐标。第一对表示窗口内鼠标指针的 x 坐标和 y 坐标,第二对(root:)表示指针在整个显示屏上的位置。

其他低级事件包括按键和点击按钮,但更高级的事件表示鼠标是否进入或退出窗口,或窗口是否从窗口管理器获得或失去焦点。例如,以下是相应的退出和取消焦点事件。

LeaveNotify event, serial 36, synthetic NO, window 0x6800001,     root 0xbb, subw 0x0, time 44348653, (55,185), root:(1679,420),     mode NotifyNormal, detail NotifyNonlinear, same_screen YES,     focus YES, state 0  FocusOut event, serial 36, synthetic NO, window 0x6800001,     mode NotifyNormal, detail NotifyNonlinear 

xev 的一个常见用途是在重映射键盘时提取不同键盘的按键代码和按键符号。下面是按 L 键的输出;这里的键码是 46:

KeyPress event, serial 32, synthetic NO, window 0x4c00001,     root 0xbb, subw 0x0, time 2084270084, (131,120), root:(197,172),     state 0x0, keycode 46 (keysym 0x6c, l), same_screen YES,     XLookupString gives 1 bytes: (6c) "l"     XmbLookupString gives 1 bytes: (6c) "l"     XFilterEvent returns: False 

你也可以使用 -id id 选项将 xev 附加到现有窗口 ID 上。将 id 替换为从 xwininfo 获取的 ID(以 0x 开头的十六进制数字)。

参考资料

14.4.5 X 输入和首选项设置

X 最令人困惑的特点之一是,通常有不止一种方法来设置首选项,而且有些方法可能不起作用。例如,Linux 系统上一种常见的键盘首选项是将 CAPS LOCK 键重新映射为 CTRL 键。有很多方法可以做到这一点,从使用旧的 xmodmap 命令进行微小调整,到使用 setxkbmap 实用程序提供全新的键盘映射,不一而足。如何知道使用哪种方法(如果有的话)?这需要了解系统中哪些部分需要负责,但确定这一点可能很困难。请记住,桌面环境可能会提供自己的设置和覆盖。有鉴于此,以下是一些有关底层基础架构的提示。

  • 输入设备(一般)
    X 服务器使用 X 输入扩展来管理来自许多不同设备的输入。输入设备有两种基本类型--键盘和指针(鼠标)--你可以根据需要附加多种设备。要同时处理多个相同类型的设备,X 输入扩展会创建一个虚拟核心设备,将设备输入传送到 X 服务器。

要查看机器上的设备配置,请运行 xinput --list 命令:

$ xinput --list ∣ Virtual core pointer                           id=2    [master pointer  (3)] ∣   ↳Virtual core XTEST pointer                 id=4    [slave  pointer  (2)] ∣   ↳ Logitech Unifying Device                  id=8    [slave  pointer  (2)] ⌊ Virtual core keyboard                          id=3    [master keyboard (2)]     ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]     ↳ Power Button                              id=6    [slave  keyboard (3)]     ↳ Power Button                              id=7    [slave  keyboard (3)]     ↳ Cypress USB Keyboard                      id=9    [slave  keyboard (3)] 

每个设备都有一个相关的 ID,可用于 xinput 和其他命令。在此输出中,ID 2 和 3 是核心设备,ID 8 和 9 是实际设备。请注意,机器上的电源按钮也被视为 X 输入设备。

大多数 X 客户端都会监听来自核心设备的输入,因为它们没有理由关心是哪个特定设备启动了事件。事实上,大多数客户端对 X 输入扩展一无所知。不过,客户端可以使用扩展来识别特定设备。

每个设备都有一组相关属性。要查看属性,请使用 xinput 并输入设备编号:

$ xinput --list-props 8 Device 'Logitech Unifying Device. Wireless PID:4026':         Device Enabled (126):   1         Coordinate Transformation Matrix (128): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000         Device Accel Profile (256):     0         Device Accel Constant Deceleration (257):       1.000000         Device Accel Adaptive Deceleration (258):       1.000000         Device Accel Velocity Scaling (259):    10.000000 --snip-- 

您可以使用 --set-prop 选项更改一些属性。更多信息,请参阅 xinput(1) 手册页面。

  • 鼠标
    你可以使用 xinput 命令操作与设备相关的设置,其中许多最有用的选项与鼠标(指针)有关。你可以直接以属性的形式更改许多设置,但通常使用 xinput 的专门选项 --set-ptr-feedback 和 --set-button-map 会更方便。举例来说,如果你有一个三键鼠标,你想颠倒它的按键顺序(这对左撇子用户很方便),可以试试下面的方法:
$ xinput --set-button-map dev 3 2 1 
  • 键盘

国际上有许多不同的键盘布局,这给集成到任何窗口系统中带来了特别的困难。X 的核心协议中一直都有内部键盘映射功能,你可以使用 xmodmap 命令对其进行操作,但任何中途更新的系统都会使用 XKB(X 键盘扩展)来获得更精细的控制。

XKB 非常复杂,以至于许多人在需要快速更改时仍在使用 xmodmap。XKB 的基本思想是定义一个键盘映射,使用 xkbcomp 命令对其进行编译,然后使用 setxkbmap 命令在 X 服务器中加载并激活该映射。该系统有两个特别有趣的功能:

你可以定义部分映射来补充现有映射。这对于将 CAPS LOCK 键变为 CTRL 键等任务特别方便,许多桌面环境中的图形键盘首选项实用程序都使用了这一功能。

您可以为每个附加键盘定义单独的映射。

  • 桌面背景
    X 服务器的根窗口是显示屏的背景。旧的 X 命令 xsetroot 允许你设置根窗口的背景颜色和其他特征,但这对大多数机器没有影响,因为根窗口从来不可见。相反,大多数桌面环境都会在所有其他窗口后面放置一个大窗口,以便启用 “活动壁纸 ”和桌面文件浏览等功能。有一些方法可以通过命令行更改背景(例如,在某些 GNOME 安装中使用 gsettings 命令),但如果你真的想这样做,你可能有太多时间了。

  • xset
    最古老的首选项命令可能是 xset。它现在已经不常用了,但你可以快速运行 xset q 来获取一些功能的状态。最有用的可能是屏幕保护程序和显示电源管理信号(DPMS)设置。

14.5 D-Bus

桌面总线(D-Bus)是 Linux 桌面最重要的开发成果之一,它是一种消息传递系统。D-Bus 之所以重要,是因为它是一种进程间通信机制,允许桌面应用程序相互通信,而且大多数 Linux 系统都使用它来通知进程系统事件,如插入 USB 驱动器。

D-Bus 本身由一个库组成,该库将进程间通信标准化,为任何两个进程之间的对话提供协议和支持功能。就其本身而言,D-Bus 库不过是普通 IPC 设施(如 Unix 域套接字)的一个花哨版本。使 D-Bus 有用的是一个名为 dbus-daemon 的中心 “枢纽”。需要对事件做出反应的进程可以连接到 dbus-daemon,并注册接收特定类型的事件。连接的进程也会创建事件。例如,进程 udisks-daemon 监控 udev 的磁盘事件并将其发送给 dbus-daemon,然后 dbus-daemon 再将事件转发给对磁盘事件感兴趣的应用程序。

14.5.1 系统和会话实例

D-Bus 已成为 Linux 系统不可分割的一部分,现在它的应用范围已超出桌面。例如,systemd 和 Upstart 都有 D-Bus 通信通道。不过,在核心系统内部为桌面工具添加依赖关系违背了 Linux 的设计规则。

为了解决这个问题,实际上有两种 dbus-daemon 实例(进程)可以运行。第一种是系统实例,在启动时由 init 使用 --system 选项启动。系统实例通常以 D-Bus 用户身份运行,其配置文件为 /etc/dbus-1/system.conf(不过你可能不应该更改配置)。进程可以通过 /var/run/dbus/system_bus_socket Unix 域套接字连接到系统实例。

独立于系统 D-Bus 实例的是一个可选的会话实例,它只在启动桌面会话时运行。您运行的桌面应用程序会连接到该实例。

14.5.2 D-Bus 消息监控
查看系统和会话 dbus-daemon 实例之间差异的最佳方法之一是监控总线上的事件。请尝试在系统模式下使用 dbus-monitor 实用程序,如下所示:

# dbus-monitor --system signal sender=org.freedesktop.DBus -> dest=:1.952 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired    string ":1.952" 

这里的启动信息表明监视器已连接并获取了一个名称。这样运行时应该不会看到太多活动,因为系统实例通常并不繁忙。要想看到活动发生,可以尝试插入 USB 存储设备。

相比之下,会话实例要忙得多。假设您已登录到桌面会话,请试试下面的方法:

$ dbus-monitor --session 

现在尝试使用一个桌面应用程序,如文件管理器;如果你的桌面能感知 D-Bus,你应该会收到大量显示各种变化的信息。请记住,并非所有应用程序都会产生信息。

14.6 打印

在 Linux 上打印文件是一个多阶段的过程:

  • 进行打印的程序通常会将文档转换成 PostScript 格式。这一步是可选的。
  • 程序将文档发送到打印服务器。
  • 打印服务器收到文档后会将其放入打印队列。
  • 当打印队列轮到文档时,打印服务器会将文档发送到打印过滤器。
  • 如果文档不是 PostScript 格式,打印过滤器可能会进行转换。
  • 如果目标打印机不懂 PostScript,打印机驱动程序就会将文档转换为与打印机兼容的格式。
  • 打印机驱动程序会在文档中添加可选说明,如纸盘和双面打印选项。
  • 打印服务器使用后台将文档发送到打印机。

这个过程中最令人困惑的部分就是为什么这么多的内容都围绕着 PostScript。PostScript 实际上是一种编程语言,因此当你使用它打印文件时,就是在向打印机发送一个程序。PostScript 是 Unix 系统中的打印标准,就像 .tar 格式是归档标准一样。(现在有些应用程序使用 PDF 输出,但转换起来相对容易)。

稍后我们将详细讨论打印格式,但首先让我们来看看队列系统。

14.6.1 CUPS

Linux 中的标准打印系统是 CUPS (http://www.cups.org/),它与 macOS 上使用的系统相同。CUPS 服务器守护进程名为 cupsd,你可以使用 lpr 命令作为简单的客户端向守护进程发送文件。

CUPS 的一个重要特点是它实现了互联网打印协议(IPP),这是一个允许客户端和服务器在 TCP 631 端口上进行类似 HTTP 交易的系统。事实上,如果你的系统上运行了 CUPS,你就可以连接到 http://localhost:631/ 查看当前配置并检查任何打印机作业。大多数网络打印机和打印服务器都支持 IPP,Windows 也是如此,这使得设置远程打印机变得相对简单。

你可能无法通过网络界面来管理系统,因为默认设置不是很安全。相反,你的发行版可能有一个图形设置界面,用于添加和修改打印机。这些工具可操作配置文件,通常位于 /etc/cups。通常最好让这些工具代劳,因为配置可能很复杂。即使遇到问题需要手动配置,通常也最好使用图形工具创建打印机,这样就有了开始的地方。

14.6.2 格式转换和打印过滤器

许多打印机,包括几乎所有低端型号,都不懂 PostScript 或 PDF。要支持这些打印机,Linux 打印系统必须将文档转换为打印机专用的格式。CUPS 会将文档发送到光栅图像处理器 (RIP) 以生成位图。RIP 几乎总是使用 Ghostscript (gs) 程序来完成大部分实际工作,但这有点复杂,因为位图必须符合打印机的格式。因此,CUPS 使用的打印机驱动程序会查阅特定打印机的 PostScript 打印机定义 (PPD) 文件,以确定分辨率和纸张大小等设置。

14.7 其他桌面主题

Linux 桌面环境的一个有趣特点是,你通常可以选择你想使用的部分,并停止使用你不喜欢的部分。要了解各种桌面项目,请访问 https://www.freedesktop.org/ 上的邮件列表和项目链接。

Linux 桌面的另一个重大发展是 Chromium OS 开源项目和 Chromebook PC 上的谷歌 Chrome OS。这是一种 Linux 系统,使用了本章所述的大部分桌面技术,但其核心是 Chromium/Chrome 网页浏览器。Chrome OS 去掉了传统桌面上的许多功能。

虽然在桌面环境上进行观察和实验很有趣,但我们还是需要在这里结束讨论。不过,如果本章引起了你的兴趣,并且你认为自己可能会喜欢使用它们,那么你就需要了解开发者工具是如何工作的,这也是我们接下来要讨论的内容。