图形化是一个复杂的技术,在 Linux 下面更是如此。本文尝试介绍 Linux 实现图形化的方方面面。
硬件
在介绍图形化技术之前,首先介绍一下图形化相关硬件的工作原理。
显示器
显示器屏幕上显示的内容由一系列的像素组成,这些像素信息由主机传输给显示器。通用的显示器接口有 VGA 和 HDMI 两种,这里以 VGA 为例。VGA 接口有 15 根针,传输的是模拟信号
显卡
集成显卡和独立显卡。集成显卡是主板的一部分,没有自己的存储器,而是使用系统内存工作。独立显卡拥有自己的专用内存、内部总线甚至包括风扇,是一个自主程度相当高的组件。独立显卡并不一定是可拆卸的,尤其是在笔记本电脑上。
现代的 GPU 的功能包括:
将内容显示到屏幕上
2D 加速
3D 加速
视频解码
科学计算
显卡包含显示输出接口,如 VGA、HDMI 等。显示输出时,图像信息首先保存在 Framebuffer 中,显卡会根据显示器的刷新频率将图像信息转换成信号流,编码器将数字信号转换为 VGA 的模拟信号,通过插槽输送到显示器。这里说到的 Framebuffer 是显卡存储器中的一部分,里面存储的信息正式屏幕上最终显示的内容,具体的格式与显示器设置有关。
通常主板有集成显卡,因此具有显示输出接口。NVIDIA 和 AMD 的独立显卡也带有显示输出,当为电脑接上独立显卡之后,主板一般会关闭自带的视频输出,这时用户必须换成使用独立显卡上的输出接口连接显示器。
集显和独显的关系有两种:
第一种称作 MUX 或 MUXed System。这种系统下,集显和独显都有视频输出接口,都可以向显示器输出信号,系统通过一个数据选择器(Multiplexer,简称 mux)控制哪一个显卡的输出信号传输到显示器上。
另一种称作 MUXless System,只有集成显卡能够输出视频信号,而独立显卡只能进行渲染和计算,不负责视频输出。
向量显示器(vector display)是早期的一种显示器,这种显示器显示的图像不是由像素组成,计算机控制显示器的电子束从一个点移动到另一点,从而绘制一条线段。
显卡能够向显示器输出视频信号,但是显示器的显示模式需要操作系统进行设置。
总线
在冯诺依曼体系架构中,CPU 需要和周边设备通信,总线就是通信的媒介。
早期的计算机,设备类型和数量相对固定,因此设备之间使用专用的总线组成全连接结构。总线的出现使得设备全都连接到一根线缆上,使得组织更加简单,也让计算机更具有扩展性。
PC 遵循冯诺依曼架构,CPU 是计算机的核心组件,其他硬件作为周边设备存在,例如内存、显卡、网卡等。总线将 CPU 和周边设备连接起来,使 CPU 能够访问并控制其他设备,例如读写内存。然而,CPU 并不是唯一能够和周边设备进行数据通信的设备,某些设备自身就有主动能力,能够在没有 CPU 帮助的情况下进行数据交换。例如,硬盘能够主动将磁盘数据写入内存,这样的能力称为直接内存访问(DMA)。
GPU 需要访问内存,才能完成相应图形运算。CPU 通过分页机制管理内存,GPU 和其他设备同样有这种管理内存的能力,通过 IOMMU 实现。设备所使用的内存地址也不是物理地址,只有经过 IOMMU 翻译之后的才是最终地址。
现在的显卡结构非常复杂,俨然是计算机里的另一个计算机。显卡的核心——GPU,同样具有自己的指令集和寄存器,拥有自己的体系架构,AMD 甚至还公开了一些 GPU 的指令集,NVIDIA 的 GPU 指令集虽然不公开,但是 noveaou 项目一直致力于逆向 NV 驱动。AMD 的 GPU 基于 VLIW(Very Long Instruction Word,超长机器字),NVIDIA 的 GPU 基于超标量体系(这也是两种显卡在挖矿上相差悬殊的原因)。
History
计算机图形学起源很早,但是把图形作为用户界面,
X Server
1985 年的时候,Linux 还没有出现,当时主流的操作系统是 Unix。X 是 MIT 开发的 Unix 下的显示系统。当时的 Unix 系统没有动态链接库,因此要在图形应用之间共享绘图代码的唯一办法,就是使用协议通信,将所有绘图的代码全部放在 X Server 中。
后来在 X 的发展过程中,加入了一些网络不透明的协议,因此现在的 X 虽然仍然是 Client/Server 架构,但已经不能显示远程计算机上的应用了(但是现在已经有了更好的解决方案,如 VNC,或者直接使用 Web 应用)。
许多关于 X 的介绍都说 C/S 的架构非常灵活,但是如今这些已经成了 X 的历史包袱。
Linux 早期,系统中唯一能够与 显示设备
X 不仅负责绘图,还需要处理鼠标、键盘输入和内存管理。Linux 下 evdev 负责提供输入设备的支持,GEM 进行渲染和内存管理,KMS 负责模式设置(驱动中大量代码都是属于模式设置的)。
Key mapping –> libxkbcommon
Linux 下闭源显卡驱动往往采取不一样的架构。闭源驱动包含两个部分,一部分处在用户层,作为动态链接库与 3D 应用程序链接在一起,负责和内核中的驱动部分通信。内核模块部分负责与硬件进行交互和一些同步操作。用户部分和内核部分之间的交互方式是驱动开发者需要解 决的,闭源驱动往往采取独立的实现,在开源驱动中,这种机制就是 DRI。
来源:oschina
链接:https://my.oschina.net/u/114411/blog/535164