linux GUI 如何在最低级别工作?

poo*_*123 51 linux gui hardware system-calls linux-kernel

我基本上是想弄清楚如何从头开始制作一个 GUI,除了 linux 内核和 C 编程之外什么都没有。

我不打算从头开始创建 GUI 桌面环境,但我想创建一些桌面应用程序,并且在我搜索知识的过程中,我能找到的所有信息都是关于 GUI API 和工具包的。我想知道,至少我对 Linux GUI 是如何制作的基本原理的理解,如何在不使用任何 API 或工具包的情况下制作 GUI 环境或 GUI 应用程序。

我想知道例如:

  1. 现有的 API 和工具包通过对内核的系统调用工作(内核负责在最低级别以像素或其他方式构建 GUI 图像)

  2. 这些工具包执行简单地将信息传递给屏幕驱动程序的系统调用(是否有发送所有屏幕驱动程序都遵守的信息的标准格式,或者 GUI API 是否需要能够根据特定的屏幕/驱动程序以多种格式输出此信息? ) 并且如果这大致正确,原始的 linux 内核是否通常只以 8 位字符的形式将信息发送到屏幕?

我真的很想了解 linux 内核之间发生了什么,以及我在屏幕上看到的内容(通过软件和硬件的控制/信息流,如果您知道,信息采用什么格式等)。我非常感谢详细的解释,我知道这可能很难解释得足够详细,但我认为这样的解释对于其他好奇和学习的人来说将是一个很好的资源。对于上下文,我是一名 3 年级的 Comp sci 学生,他最近开始在我的系统编程课程中使用 C 进行编程,并且我对 linux 和编程有中级(或者我会描述它)的理解。再次感谢所有帮助我的人!!!

ctr*_*lor 66

工作原理 (Gnu/Linux + X11)

概述

它看起来像这样(不按比例绘制)

?????????????????????????????????????????????????
?                       User                    ?
?     ???????????????????????????????????????????
?     ?             Application                 ?
?     ?            ??????????????????????????????
?     ?            ?      ... ? SDL ? GTK ? QT  ?
?     ?            ??????????????????????????????
?     ?            ?            xLib            ?
?     ?            ??????????????????????????????
???????????????????????         X11             ?
?   Gnu   ? Libraries ?        Server           ?
?   Tools ?           ?                         ?
???????????           ?                         ? 
???????????????????????                         ?
?   Linux (kernel)    ?                         ?
?????????????????????????????????????????????????
?                    Hardware                   ?
?????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

我们从图中可以看出 X11 主要与硬件对话。然而,它需要通过内核进行通信,以最初访问该硬件。

我对细节有点模糊(我认为自从我上次调查以来它发生了变化)。有一个设备/dev/mem可以访问整个内存(我认为是物理内存),因为大多数图形硬件都是内存映射的,这个文件(见一切都是文件)可以用来访问它。X11 会打开文件(内核使用文件权限来查看它是否可以这样做),然后 X11 使用mmap将文件映射到虚拟内存(使其看起来像内存),现在内存看起来像内存。之后mmap,不涉及内核。

X11 需要了解各种图形硬件,因为它通过内存直接访问它。

(这可能会发生变化,特别是安全模型,可能不再允许访问所有内存。)

Linux

底层是 Linux(内核):系统的一小部分。它提供对硬件的访问,并实现安全性。

牛牛

然后是 Gnu(库;bash;工具:ls 等;C 编译器等)。大多数操作系统。

X11 服务器(egxorg)

然后是 X11(或 Wayland,或 ...),基本 GUI 子系统。这运行在用户空间(内核之外):它只是另一个进程,具有一些特权。内核不参与,除了提供对硬件的访问。并提供进程间通信,让其他进程可以与X11服务器进行对话。

X11库

允许您为 X11 编写代码的简单抽象。

图形用户界面库

下一个是诸如 qt、gtk、sdl 之类的库——它们使 X11 的使用更容易,并且可以在其他系统上工作,例如 Wayland、Microsoft 的 Windows 或 MacOS。

应用

应用程序位于库之上。

一些低级入口点,用于编程

使用 xlib 是了解 X11 的好方法。但是,请先阅读有关 X11 的一些信息。

SDL

SDL 将为您提供低级访问权限,直接访问位平面供您直接绘制。

走低

如果你想降低,那么我不确定当前有哪些好的选择,但这里有一些想法。

链接

X11

https://en.wikipedia.org/wiki/X_Window_System

现代方式

写这个引起了我的兴趣,所以我看看现代快速的方法是什么。以下是一些链接:

https://blogs.igalia.com/itoral/2014/07/29/a-brief-introduction-to-the-linux-graphics-stack/

  • 很好的答案,但我确实认为缺少一些重要的东西:DRI,直接渲染基础设施。有了这个,应用程序几乎直接在 Xorg 和内核的监督下直接寻址硬件(很像 Xorg 在内核的最少监督下主要寻址硬件本身)。例如,这被广泛用于通过 libmesa 进行硬件加速的 OpenGL。当然,现在有 Wayland 取代了 Xorg,但当然在抽象位置略有不同。这是一个复杂的景观:) (16认同)
  • X11 是一种协议:它不与硬件通信,它是在客户端(“应用程序”)和服务器(可能是 x.org)之间发送的格式化数据。X11 服务器本身也不与硬件通信以获取输出,而是使用各种文件 I/O 和内核的 ioctl 接口与输入通信。输出通常通过其他内核 API(如 DRM)完成,以填充帧缓冲区并与专用绘图硬件(如 GPU)对话。基本上,构建 GUI 意味着通过内核 API 发送和接收数据。 (10认同)
  • 正如 marcelm 所说,如今的硬件访问通过 DRI(或 DRM)进行。`/dev/mem` 现在提供对很少内存的访问。还有所有的输入堆栈,现在隐藏在 `libinput` 和 `libevdev` 后面。 (4认同)
  • @poopoopeepee123 我想指出 X11 本身(API 部分)只是一个通过 TCP/IP 运行的协议(在您的机器上,您的应用程序连接到本地主机)。这使得 X11 非常灵活,能够在不同的计算机上运行 GUI 程序并在不同的计算机上甚至在不同的国家/地区显示它。如果您研究协议,这也使得可以直接使用标准网络编程与 X11 对话,而无需使用 xlib(这也是人们如何通过拦截 X11 事件来编写剪贴板管理器之类的东西) (4认同)
  • 在 X11 和硬件之间有一个额外的层——设备驱动程序。但是由于设备驱动程序是一个内核模块,你可以说它是内核的一部分 (2认同)

Her*_*ann 34

ctrl-alt-delor 的回答为您提供了总体架构的良好概述。对于更实际的方法,我给你一个关于“除了 linux 内核和 C 编程”的答案。

我喜欢时不时地直接写入帧缓冲区。帧缓冲设备驱动程序将为您完成所有乏味的接近硬件的“这将如何最终出现在屏幕上”的事情。您可以立即使用 root shell 执行此操作:

echo -n -e '\x00\x00\xFF' > /dev/fb0
Run Code Online (Sandbox Code Playgroud)

它将我的 32 位帧缓冲区上的第一个(左上角)像素设置为红色:

帧缓冲区的屏幕截图,左上角像素为红色

您可以通过打开 /dev/fb0 并写入字节从 C 中完全做到这一点。内存映射可以成为你的朋友。这仅适用于没有 X 服务器或在虚拟控制台中的情况。按 Ctrl+Alt+F1 访问它。

PS:将鼠标移动等随机数据可视化也很有趣:

cat /dev/input/mouse0 > /dev/fb0
Run Code Online (Sandbox Code Playgroud)

PPS:还请注意,几乎所有真实世界的桌面应用程序都希望更直接地访问硬件以获取一些奇特的东西,例如绘图、3D 和视频渲染的硬件加速。简单的帧缓冲设备不能很好地完成这些工作。

  • 鼠标到帧缓冲区是我一整天最有趣的 (6认同)

Gra*_*ham 6

我强烈建议从ncurses开始。

与更复杂的图形系统不同,它完全基于文本,因此无需陷入屏幕驱动程序和图形库的细节中。然而,将窗口放在屏幕上、在窗口之间移动焦点等基本原则仍然适用。而且您仍然可以在单个字符块和 ASCII 艺术级别进行一些绘图。

当然,您仍然在库之上构建它,但它是一个您可以轻松理解的库。更重要的是,它是一个库,其中的源代码是免费提供的,文档相当齐全,如果您想阅读它也不会太难理解。如果你愿意,你甚至可以自己修改它。或者您可以查看其中的所有库函数以找到 API 需要的内容,然后根据该设计自己从头开始编写。

  • “我强烈建议从护士开始” 迄今为止最好的建议。 (8认同)
  • 您可能指的是 [ncurses](https://en.wikipedia.org/wiki/Ncurses),它*不是*图形用户界面,而是文本用户界面。 (7认同)