文章目录
- 一、Linux显示框架
- 二、Qt在Linux的显示
-
- [1、Qt在Linux运行时是如何选择显示框架插件的?(编译时 ?? 运行时)](#1、Qt在Linux运行时是如何选择显示框架插件的?(编译时 ?? 运行时))
- 2、Qt的eglfs插件的作用
- 三、Linux中Qt开机自启问题
-
- 1、Linux程序实现开机自启的方法(systemd)
- 2、systemd服务
- 3、systemd的统一日志管理工具Journald
-
-
- 1、实时日志滚动查看
- [2、查看内核日志(等价 dmesg)](#2、查看内核日志(等价 dmesg))
- [3、 按时间筛选日志(精准定位问题,高频)](#3、 按时间筛选日志(精准定位问题,高频))
- [4、查看指定程序 / 进程的日志](#4、查看指定程序 / 进程的日志)
- [5、按日志级别筛选(只看「报错 / 警告」,过滤无用日志](#5、按日志级别筛选(只看「报错 / 警告」,过滤无用日志)
- 6、查看崩溃原因和堆栈日志
- 7、指定显示行数
- 8、日志的清理和存储
- [9、journalctl vs dmesg 区别(嵌入式开发必懂)](#9、journalctl vs dmesg 区别(嵌入式开发必懂))
-
- [4、Systemd 的 Unit 文件](#4、Systemd 的 Unit 文件)
- 5、Uinti文件格式
- 6、Unit段参数
- [7、Install 段参数](#7、Install 段参数)
- 8、Server段
- [9、systemd启动失败排查(2026/01/19 添加)](#9、systemd启动失败排查(2026/01/19 添加))
- [10、启动慢如何排查(2026/01/19 添加)](#10、启动慢如何排查(2026/01/19 添加))
- 注意
- 四、EGLFS下Qt的启动文件
- 四、问题
-
-
- [1、elgfs framebuffer 是无桌面环境的,Qt程序基于elgfs 或者 framebuffer启动后是否可以获取触摸事件??](#1、elgfs framebuffer 是无桌面环境的,Qt程序基于elgfs 或者 framebuffer启动后是否可以获取触摸事件??)
- 2、嵌入式触摸屏存在触摸点偏移的情况,能不能在不改动驱动的情况下校准输入(只正对Qt程序)
- [3、eglfs是不是所有嵌入式Linux设备都支持,Qt 只有eglfs插件。在有桌面的情况下关闭桌面后是不是可以直接运行??](#3、eglfs是不是所有嵌入式Linux设备都支持,Qt 只有eglfs插件。在有桌面的情况下关闭桌面后是不是可以直接运行??)
- 4、在有桌面时如何使用EGLFS显示QT
- [5、gdm不启动的话 xorg或者 weston就不会启动吗?](#5、gdm不启动的话 xorg或者 weston就不会启动吗?)
-
最近在做一个嵌入式Qt项目,板卡运行Ubuntu。由于用户变更了几次Ubuntu版本,导致Qt界面在有些环境可以显示,在有些环境不能正常显示。准备了解一下Linux的显示框架和Linux中Qt界面的显示原理。
一、Linux显示框架
参考博客1 Linux 图形与显示软件架构总览
参考博客2 Linux DRM 图形与显示框架详解
1、DRM框架
比较复杂,理解的还不到位,后期补充。
2、X11 和 Wayland (xorg 和 weston)
1、X11(逐渐被wayland取代)
首先明确一点,X11 是 Linux显示的一种协议(Wayland也是一种)。xorg 是 X11协议的实现(好比 TCP/IP 协议 和 Lwip)。
X11
X11的全称是 X Window System Version 11,是 1987 年诞生的一套跨平台图形界面通信协议,也是 Linux/Unix 系统图形界面的基石,核心定义了「图形客户端」和「图形服务器」之间的交互规则。X11 的核心架构是 客户端 - 服务器(C/S)架构。X11 的「服务器」是本地的显示 + 输入设备管理器,「客户端」是需要显示的应用程序。
X11 将任何需要图形显示的程序(如 Qt 程序、文本编辑器、浏览器),都作为 X11 客户端,向 X11 服务器发送「绘制窗口」「显示文字」等请求,不直接操作硬件。
X11 的服务器负责管理本地的显示器、键盘、鼠标等硬件,接收客户端的渲染请求,处理后输出到屏幕,同时将输入事件(按键、触摸)转发给对应的客户端。
X11 协议支持网络传输,客户端和服务器可以不在同一台设备(比如远程运行 Qt 程序,界面显示在本地屏幕),这是它的历史核心优势,但也是性能瓶颈(网络延迟 + 多层转发)。
X11 定义了一套标准化的接口,让图形应用无需关心底层硬件差异(比如不同显卡、显示器),只需遵循协议和 X11 服务器通信即可。它是 Linux 桌面环境(如 GNOME 2、KDE 4)和早期嵌入式图形界面的基础。
Xorg
Xorg的全称是 X.Org Server,是遵循 X11 协议的开源显示服务器程序,是用户态中实际管理图形硬件的核心进程(运行时进程名为 X 或 Xorg)。实现 X11 协议的全部核心接口,作为 X11 服务器接收客户端的渲染请求。
向下对接硬件:通过 DRM(Direct Rendering Manager)+ OpenGL/EGL 调用 GPU 硬件加速,管理显示器分辨率、刷新率,对接键盘 / 触摸等输入设备。
向上支撑应用:为 Qt、GTK 等图形框架提供显示能力,Qt 对接 Xorg 需启用 xcb 插件(编译参数 -xcb)。
2、Wayland
Wayland
Wayland 是一套图形界面通信协议标准,Weston 是 Wayland 协议的官方开源参考实现(可直接运行的 Wayland 合成器 / 显示服务器)。 Wayland 是 2008 年提出的一套跨平台、轻量化的图形界面通信协议,设计初衷是解决 X11 协议的历史缺陷(多层转发、性能损耗、代码臃肿),核心针对现代 GPU 硬件和嵌入式 / 桌面场景做了优化。
Wayland特点
- 无中间转发的架构设计:摒弃 X11「客户端 - 服务器」的多层转发模式,定义了「Wayland 客户端」(界面程序)和「Wayland 合成器(Compositor)」两个核心角色,客户端直接完成自身离屏渲染,仅将渲染结果提交给合成器,无多余指令转发。
- 硬件访问独占性:协议规定「合成器独占系统 DRM 设备(/dev/dri)和显示资源」,是唯一能对接底层 GPU / 显示硬件的角色,客户端无法直接访问硬件,只能通过合成器提供的共享缓冲区传递数据,避免资源冲突。
- 轻量化与低延迟 :协议本身简洁,无 X11 大量的历史兼容扩展,聚焦于「渲染结果提交」和「输入事件分发」的核心功能,运行开销小、响应延迟低,天生适配嵌入式场景。
跨场景支持:既支持桌面环境(多窗口、拖拽、缩放),也支持嵌入式单 / 多应用场景,兼顾灵活性和高效性。
weston功能
- 独占并管理硬件资源:启动后独占 /dev/dri(DRM 设备)、/dev/fb0(帧缓冲)和输入设备(/dev/input/eventX),对接 GPU 驱动(EGL/OpenGL ES)和显示面板。
- 接收客户端渲染结果:通过 Wayland 协议,接收所有 Wayland 客户端(如 Qt 程序)提交的离屏缓冲区数据,缓存并记录每个客户端窗口的位置、层级、大小。
- 多客户端数据合成:利用 EGL/OpenGL ES 创建合成上下文,将多个客户端的缓冲区数据作为纹理,完成窗口叠加、缩放、Alpha 混合等合成操作,生成一帧完整的屏幕像素数据。
- 对接 DRM 完成显示输出:合成完成后,通过 libdrm 库调用 DRM 内核子系统的「页翻转」接口,将最终帧数据提交到显示面板,完成界面输出。
- 输入事件分发:监听输入设备节点,将触摸、键鼠事件通过 Wayland 协议分发给对应的客户端程序,实现用户交互。
weston的功能可以通过weston.ini 进行裁剪。运行时进程名为 weston,启动后会自动创建 Unix 域套接字(默认 wayland-0),作为与客户端通信的通道。无需额外的显示管理器(如 GDM),可直接在 TTY 控制台启动,适合嵌入式无桌面场景。支持多种后端(DRM 后端、fbdev 后端、X11 后端),其中 DRM 后端是嵌入式场景的首选(支持硬件加速)。
3、在Linux存在桌面环境时如何确定是X11 还是 Wayland
直接查看相关进程
powershell
# 检查是否有 Xorg 进程(X11 会话的核心进程)
ps aux | grep -E "Xorg|X" | grep -v grep
# 检查是否有 Wayland 合成器进程(如 Weston、gnome-shell、kwin_wayland)
ps aux | grep -E "weston|gnome-shell|kwin_wayland" | grep -v grep
注意
1、X11的服务器xorg 和 Waylan的合成器weston 会独占 DRM
2、GDM:上层的会话管理器,负责登录和启动显示服务器,非必需组件。
二、Qt在Linux的显示
1、Qt在Linux运行时是如何选择显示框架插件的?(编译时 ?? 运行时)
在交叉编译Qt源码阶段,编译多个平台插件Wayland/eglfs/linuxfb,程序编译时不需要指定插件(基于那种环境)。在程序运行时通过参数 或者 环境变量QT_QPA_PLATFORM确定使用哪个插件。
如果在交叉编译是没有交叉编译需要的平台插件动态库,比如:没有编译 wayland插件,但是程序运行时指定了环境变量export QT_QPA_PLATFORM=wayland
或者指定了参数 ./your_qt_app -platform wayland,则程序会因为找不到插件的动态库而报错。如果没有指定参数,也没有指定动态库则Qt程序会自动探测可使用的
插件(适配当前环境)。
2、Qt的eglfs插件的作用
EGLFS 是一个平台插件,用于在 EGL 和 OpenGL ES 2.0 上运行 Qt 应用程序,而无需 X11 或 Wayland 等实际窗口系统。它是包含 GPU 的现代嵌入式 Linux 设备的推荐插件。所以,EGLFS可以调用EGL 和 OpenGL ES 2.0 的API,实现Qt和平台的对接。除了Qt Quick 和本地 OpenGL 应用程序外,EGLFS 还支持软件渲染窗口,如QWidget 。对于QWidget ,小部件的内容通过 CPU 渲染成图像,然后由插件上载成纹理并合成。
EGLFS 强制第一个顶级窗口(QWidget 或QQuickView )变成全屏。该窗口也被选为根窗口,所有其他顶层窗口都在其中合成。例如,对话框、弹出式菜单或组合框。这种行为是必要的,因为在 EGLFS 中,总是存在一个本地窗口和一个 EGL 窗口表面;它们都属于最先创建的部件或窗口。当应用程序的整个生命周期中都存在一个主窗口,而所有其他窗口小部件要么不是顶层的,要么是在主窗口显示后才创建的时候,这种方法就非常有效。
三、Linux中Qt开机自启问题
参考文章1 可能是史上最全面易懂的 Systemd 服务管理教程!
1、Linux程序实现开机自启的方法(systemd)
在现代 Linux下systemd服务是最好的选择。systemd 是目前绝大多数 Linux 发行版(Ubuntu、CentOS、Debian 等)的系统初始化管理器 ,也是开机自启程序的首选方案,尤其适合 Qt EGLFS 模式(无图形界面),具备「可管理、有日志、支持自重启、权限可控」等优势。还有一些方法,比如、/etc/rc.load 等一些方法。现在不做了解(暂时用不到)。
2、systemd服务
Systemd 是一系列工具的集合,其作用也远远不仅是启动操作系统,它还接管了后台服务、结束、状态查询,以及日志归档、设备管理、电源管理、定时任务等许多职责,并支持通过特定事件(如插入特定 USB 设备)和特定端口数据触发的 On-demand(按需)任务。它是系统中 PID 值为 1 的进程。
Systemd 通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。对于用户自定义的服务,Systemd 允许配置其启动依赖项目,从而确保服务按必要的顺序运行。
Systemd 提供通过 CGroup 跟踪进程关系。通过 CGroup 不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期。
3、systemd的统一日志管理工具Journald
Systemd 是一系列工具的集合, 包括了一个专用的系统日志管理服务:Journald 。Journald 用 二进制格式 保存所有的日志信息.Journald 还提供了一个 journalctl 命令来查看日志信息,这样就使得不同服务输出的日志具有相同的排版格式, 便于数据的二次处理。
- 日志归属:journalctl 管理 系统所有日志:内核日志、系统服务日志、用户进程日志、串口 / 驱动日志、Qt 程序日志、自定义打印日志(printf/puts/Qt 的qDebug())全都在里面,一站式查看,不用再翻 /var/log/syslog//var/log/messages 等零散文件;
- 权限说明:普通用户执行部分命令会有限制,嵌入式开发直接用 sudo journalctl 即可(无权限顾虑,最省事),下文所有命令默认加sudo,避免权限报错。
- 核心优势:日志带时间戳、进程 PID、服务名、日志级别,支持按时间 / 进程 / 级别筛选,日志不丢失,重启系统后依然能查看历史日志。
1、实时日志滚动查看
powershell
sudo journalctl -f
2、查看内核日志(等价 dmesg)
powershell
sudo journalctl -k
# 实时滚动查看内核日志(驱动加载、串口注册、GPIO、485硬件报错)
sudo journalctl -k -f
3、 按时间筛选日志(精准定位问题,高频)
powershell
# 查看【最近1小时】的日志
sudo journalctl --since "1 hour ago"
# 查看【最近10分钟】的日志(开发调试最常用)
sudo journalctl --since "10 min ago"
# 查看【今天】的日志
sudo journalctl --since today
# 查看【指定时间段】的日志(精准定位崩溃/异常时间点)
sudo journalctl --since "2026-01-18 09:00:00" --until "2026-01-18 10:00:00"
4、查看指定程序 / 进程的日志
powershell
# 写法1:按【程序名】过滤(推荐!比如你的Qt程序叫 Serial485App)
sudo journalctl /home/root/Serial485App # 写程序的绝对路径
# 写法2:按【进程PID】过滤(程序运行后,先用ps -ef | grep Serial485App 查PID)
sudo journalctl _PID=1234
# 写法3:实时滚动查看指定程序日志(调试时开着,边运行边看日志)
sudo journalctl -f /home/root/Serial485App
5、按日志级别筛选(只看「报错 / 警告」,过滤无用日志
powershell
#emerg(紧急) > alert(告警) > crit(严重) > err(错误) > warning(警告) > notice(通知) > info(信息) > debug(调试)
# 只查看【错误日志】(最高优先级,必看!比如程序崩溃、文件打开失败、权限不足、串口报错)
sudo journalctl -p err
# 只查看【警告+错误】日志(推荐,包含警告和致命错误)
sudo journalctl -p warning
6、查看崩溃原因和堆栈日志
powershell
# 查看指定程序的崩溃日志,包含错误信息、崩溃时间、进程退出码
sudo journalctl /home/root/Serial485App -p err
# 查看所有崩溃的进程日志
sudo journalctl -p crit
7、指定显示行数
powershell
# 查看最新的100行日志
sudo journalctl -n 100
# 查看最新的100行内核日志
sudo journalctl -k -n 100
# 查看最新的100行指定程序日志,实时滚动
sudo journalctl -f -n 100 /home/root/Serial485App
8、日志的清理和存储
journalctl 的日志默认是内存日志,系统重启后所有日志都会丢失!
powershell
##### 存储 ######
# 1. 创建日志存储目录
sudo mkdir -p /var/log/journal
# 2. 修改journal的配置文件
sudo nano /etc/systemd/journald.conf
####在配置文件添加
Storage=persistent # 持久化存储日志到硬盘,重启不丢失
SystemMaxUse=1G # 日志最大占用空间1G,满了自动清理
清理
powershell
# 方式1:清理【7天前】的所有日志(推荐,保留近期日志)
sudo journalctl --vacuum-time=7d
# 方式2:清理日志,只保留【500M】的日志(按大小清理,嵌入式首选)
sudo journalctl --vacuum-size=500M
9、journalctl vs dmesg 区别(嵌入式开发必懂)
很多人会混淆这两个命令,你做串口 / 驱动 / Qt 开发,一定要分清,避免查错日志:
sudo journalctl -k → 查看完整内核日志 ,包含所有内核打印,日志带时间戳、完整信息,可筛选、可持久化、可实时滚动,推荐优先使用;
dmesg → 查看内核的环形缓冲区日志 ,日志是内存中的临时数据,重启丢失,无时间戳,只能看最新的内核打印;
等价关系:dmesg -w = sudo journalctl -k -f (实时看内核日志)
4、Systemd 的 Unit 文件
Systemd 可以管理所有系统资源,不同的资源统称为 Unit(单位)。在 Systemd 的生态圈中,Unit 文件统一了过去各种不同系统资源配置格式,例如服务的启/停、定时任务、设备自动挂载、网络配置、虚拟内存配置等。而 Systemd 通过不同的文件后缀来区分这些配置文件。
Systemd 支持的 12 种 Unit 文件类型
- automount:用于控制自动挂载文件系统,相当于 SysV-init 的 autofs 服务
- device:对于 /dev 目录下的设备,主要用于定义设备之间的依赖关系
- mount:定义系统结构层次中的一个挂载点,可以替代过去的 /etc/fstab 配置文件
- path:用于监控指定目录或文件的变化,并触发其它 Unit 运行
- scope:这种 Unit 文件不是用户创建的,而是 Systemd 运行时产生的,描述一些系统服务的分组信息
- service:封装守护进程的启动、停止、重启和重载操作,是最常见的一种 Unit 文件
- slice:用于表示一个 CGroup 的树,通常用户不会自己创建这样的 Unit 文件
- snapshot:用于表示一个由 systemctl snapshot 命令创建的 Systemd Units 运行状态快照
- socket:监控来自于系统或网络的数据消息,用于实现基于数据自动触发服务启动
- swap:定义一个用户做虚拟内存的交换分区
- target:用于对 Unit 文件进行逻辑分组,引导其它 Unit 的执行。它替代了 SysV-init 运行级别的作用,并提供更灵活的基于特定设备事件的启动方式
- timer:用于配置在特定时间触发的任务,替代了 Crontab 的功能
我们重点关注的是 service Unit文件,因为我们要使自己的Qt程序开机自启运行时要使用该格式文件。Target 是 Systemd 中用于指定系统资源启动组的方式,相当于 SysV-init 中的运行级别。简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于"状态点",启动某个 Target 就好比启动到某种状态。
Unit 文件按照 Systemd 约定,应该被放置指定的三个系统目录之一中。这三个目录是有优先级的。因此,在三个目录中有同名文件的时候,只有优先级最高的目录里的那个文件会被使用。
/etc/systemd/system:系统或用户自定义的配置文件
/run/systemd/system:软件运行时生成的配置文件
/lib/systemd/system:系统或第三方软件安装时添加的配置文件。
5、Uinti文件格式
Systemd 服务的 Unit 文件可以分为三个配置区段:
| 段 | 作用 |
|---|---|
| Unit | 所有 Unit 文件通用,定义服务启动的时机、依赖的其他单元(服务 / 目标),以及服务之间的启动顺序,不涉及「开机自启」的配置,仅管服务「如何正确运行」。 |
| Install | 所有 Unit 文件通用,仅在执行 systemctl enable/disable(启用 / 禁用自启)时生效,定义服务要绑定到哪个 systemd 目标(target),决定服务是否能在开机时自动启动,不影响服务的手动启动(systemctl start)。[Install] 段的核心就是将服务绑定到某个目标,当系统开机进入该目标时,自动启动该服务。 |
| Service | 服务(Service)类型的 Unit 文件(后缀为 .service)特有的,用于定义服务的具体管理和操作方法 |
6、Unit段参数
| 配置项 | 作用 | 举例 |
|---|---|---|
| Description | 描述这个 Unit 文件的信息 | |
| Documentation | 指定服务的文档,可以是一个或多个文档的 URL 路径 | |
| Requires | 定义「强制依赖」:当前服务与指定单元强绑定,指定单元启动失败会导致当前服务无法启动 / 自动停止 | (Qt EGLFS 可选)Requires=dev-dri-card0.device:确保 DRM 设备就绪后再启动 Qt 服务,设备不存在则启动失败 |
| Wants | 定义「宽松依赖」:当前服务启动时,会尝试启动指定单元,但指定单元启动失败不影响当前服务启动 | Wants=multi-user.target:依赖多用户模式,该模式启动失败不影响 Qt 服务 |
| After | 定义「启动顺序」:当前服务在指定单元之后启动(仅保证顺序,不强制依赖单元必须启动成功) | |
| Before | 与 After 相反,在启动指定的任务一个模块之间,都会首先确证当前服务已经运行 | |
| Binds To | 与 Requires 相似,失败时失败,成功时成功,但是在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启 | |
| Part Of | 一个 Bind To 作用的子集,仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动 | |
| OnFailure | 当这个模板启动失败时,就会自动启动列出的每个模块 | |
| Conflicts | 与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然 | Conflicts=gdm3.service Xorg.service:避免 Qt EGLFS 与 GDM/Xorg 同时运行(防止 DRM 资源被抢占) |
7、Install 段参数
| 配置项 | 作用 | 举例 |
|---|---|---|
| WantedBy | 定义「宽松绑定目标」:服务启用后,会在指定目标的「启动链接目录」中创建符号链接,系统进入该目标时,尝试启动该服务,服务启动失败不影响目标运行 | WantedBy=multi-user.target:绑定到多用户命令行目标,开机进入该目标时自动启动 Qt 服务 |
| RequiredBy | 定义「强制绑定目标」:服务启用后,与指定目标强绑定,系统进入该目标时,必须启动该服务,服务启动失败会导致目标启动失败 | 极少使用(风险高),如 RequiredBy=graphical.target |
8、Server段
比较多,直接去看参考文档。
9、systemd启动失败排查(2026/01/19 添加)
- journalctl 查看具体启动的日志 (绝对路径)
- 根据日志逐步排查问题
10、启动慢如何排查(2026/01/19 添加)
powershell
systemd-analyze #整体耗时
systemd-analyze blame #各服务启动顺序及时间
systemctl list-dependencies appWOFEIUI.service --all # 查看服务依赖链
systemd-analyze critical-chain #systemd 启动链,内部耗时分析
注意
systemd启动程序时和用户会话窗口启动时是不一样的。systemd环境没有一些环境变量,需要自己去在Unit设置
四、EGLFS下Qt的启动文件
powershell
[Unit]
# 服务名称,自定义,中文注释可删
Description=Qt Server Application Service (DRM/EGLFS)
Documentation=man:qt5
# 关键1:网络环境就绪后再启动,解决Qt启动后无网络/IP未配置问题
After=network-online.target network.target
# 关键2:DRM显示服务就绪后启动,适配DRM/EGLFS环境,必加
After=systemd-logind.service
# 依赖网络和DRM服务,确保前置服务启动完成
Wants=network-online.target
[Service]
# ======================== 核心配置 - 按你的需求逐条配置 ========================
# 1. 指定运行用户【必填】,多用户环境,替换为你的实际用户名,比如 pi / appuser / root
User=root
# 可选:指定用户组,和上面的User对应即可
Group=root
# 2. 启动前加载 /etc/profile 环境变量【核心需求,必配!】
# 方式:用bash的登录shell模式执行,强制加载/etc/profile + ~/.bash_profile 所有环境变量
# 完美读取里面的QT_ENV、QT_QPA_PLATFORM、IP、串口、DRM等所有配置,无遗漏
ExecStart=/bin/bash -l -c "/opt/QtApp/QtServer --platform eglfs"
# 3. 启动失败/崩溃/异常退出后,5秒自动重启【核心需求,严格匹配!】
Restart=on-failure
# 重启间隔时间:5秒,精确配置
RestartSec=5s
# 4. DRM/EGLFS环境 Qt程序 必配权限与属性【重中之重,解决90%启动失败】
# 给运行用户赋予DRM/显卡/帧缓冲/串口权限,解决EGL init failed、DRM open failed
SupplementaryGroups=video render dialout tty input
# 5. 进程守护与资源配置,生产环境最优参数
# 程序启动超时时间,防止卡死
TimeoutStartSec=30s
# 程序退出的所有异常情况都重启(包含崩溃、信号杀死、主动退出)
RestartPreventExitStatus=0
# 前台运行模式,systemd托管日志,完美对接journalctl
Type=simple
# 杀死程序时的信号,温柔退出,释放串口/DRM/网络资源
KillSignal=SIGTERM
# 强制杀死超时时间
TimeoutStopSec=5s
# 6. 屏蔽无关环境变量,防止X11/Wayland与DRM冲突,EGLFS纯净运行
Environment="QT_QPA_PLATFORM=eglfs"
Environment="QT_QPA_EGLFS_INTEGRATION=eglfs_kms"
Environment="NO_AT_BRIDGE=1"
Environment="QT_NO_GLIB=1"
Environment="DISPLAY="
Environment="WAYLAND_DISPLAY="
[Install]
# 开机自启,多用户环境下,所有用户登录都生效
WantedBy=multi-user.target
四、问题
1、elgfs framebuffer 是无桌面环境的,Qt程序基于elgfs 或者 framebuffer启动后是否可以获取触摸事件??
eglfs 支持触摸(基于evdev输入设备插件,在交缠编译时指定编译),会自动扫描输入设备(存在多个输入设备时需要通过环境变量指定具体设备)
inuxfb 本身只负责帧缓冲的渲染(CPU),也支持触摸(基于 evdev输入设备插件 或者 tslib 插件),但是效果没有eglfs好。
2、嵌入式触摸屏存在触摸点偏移的情况,能不能在不改动驱动的情况下校准输入(只正对Qt程序)
①tslib实现触摸校准,无需改动Qt和Linux驱动。tslib校准后会有一个校准文件,Qt会自动读取。
②通过QT的环境变量经过测试手动添加x和y的偏移量。不需要改动Qt程序和Linux驱动
③程序内重写触摸和鼠标的事件,每次对事件添加偏移量。需要改动Qt代码,但是更加灵活。
3、eglfs是不是所有嵌入式Linux设备都支持,Qt 只有eglfs插件。在有桌面的情况下关闭桌面后是不是可以直接运行??
硬件层面:必须具备支持 EGL/OpenGLES 的 GPU 图形核心
驱动层面:必须安装正确的 GPU 专有驱动(支持 DRM/EGL/OpenGLES)
Qt 库层面:必须正确编译并启用 eglfs 及相关依赖
只要你的设备满足上述 eglfs 支持条件,关闭桌面(Wayland/Xorg)后,无需其他额外配置(满足运行条件),即可直接运行 Qt 程序,这也是 eglfs 嵌入式场景的核心优势之一。
4、在有桌面时如何使用EGLFS显示QT
powershell
# 1. 禁用GDM开机自启
sudo systemctl disable gdm3.service
# 2. 设置系统默认启动目标为多用户命令行模式(开机直接进入TTY)
sudo systemctl set-default multi-user.target
# 3. 重启系统,使配置生效
sudo reboot
5、gdm不启动的话 xorg或者 weston就不会启动吗?
GDM(GNOME Display Manager)的核心职责之一是「用户登录后,自动启动显示服务器(Xorg 或 Weston)」,但它并不是启动 Xorg/Weston 的唯一方式,两者的关系可以总结为:
GDM 是「自动启动触发器」:Ubuntu 桌面默认配置中,GDM 开机自启,用户登录后,GDM 会根据配置(WaylandEnable=true/false)自动启动 Xorg 或 Weston,作为图形会话的显示服务器。
Xorg/Weston 可脱离 GDM 独立手动启动:GDM 不启动时,你可以在 TTY 控制台中手动执行Xorg或weston命令启动对应的显示服务器,两者没有强制的依赖关系(GDM 只是简化了「登录 + 自动启动」的流程)。
GDM 不启动 → 无自动 Xorg/Weston:如果禁用 GDM(不让其开机自启),系统开机后会直接进入 TTY 命令行模式,不会有任何图形相关进程(Xorg/Weston/GDM)运行,硬件资源(DRM / 帧缓冲 / 输入设备)处于空闲状态。
