单进程与多进程模式
应用程序管理器可以在两种不同的模式下运行系统UI和QML应用程序
- 单进程模式:在此模式下,系统UI和QML应用程序都在一个属于系统UI的单进程中运行。此模式仅支持QML应用程序 - 使用
qml
或qml-inprocess
运行时应用程序。 - 多进程模式:在此模式下,系统UI和QML应用程序各自运行在自己的专用进程中。
从内部来看,对于每个Qt应用程序,最终都是一个进程,你只能有一个Qt平台(QPA)插件。为了与底层窗口系统交互,Qt需要首先加载此插件。QPA插件决定你可以打开多少顶级窗口;但Qt在任何时候只能加载一个此类插件,并且无法在运行时替换它。如果您使用的是低级插件,即不与窗口系统通信的插件,例如在嵌入式设备上全屏的EGL,则您只能打开一个全屏窗口:系统UI。
现在,每个顶级窗口只能有一个场景图,每个QtQuick项的树只与一个场景图相关联。因此,无论应用程序是在系统UI的进程内还是在单独的进程中运行,您的系统UI都始终只有一个窗口、一个场景图和一个QML引擎。
单进程模式
单进程模式可以启用
- 特定系统应用程序以最佳性能运行,没有合成。
- 降低系统至不支持多进程模式的硬件,例如缺乏RAM/GPU资源以运行多进程模式。
- 在不支持多进程模式的平台上进行开发,例如Windows、macOS、Android、QNX,以及具有损坏Wayland驱动程序的目标。
然而,使用单进程模式会降低稳定性和可测试性:您无法单独测试您的组件,这使得诊断错误或崩溃变得困难。
在操作系统中,进程的概念与隔离的概念交织在一起。进程之间很难相互影响,操作系统尽最大努力确保这一点。这种隔离至关重要,既从安全角度,也从稳定性的角度来看。例如,如果一个进程崩溃,它不会在过程中带走另一个进程。
有时,这种隔离可能会阻碍您作为开发者进行跨边界通信。然后,您需要努力正确地做到这一点,通常通过使用专用的进程间通信机制,通常可用作API。
如果您的所有代码都在同一个进程中运行,那么您可以避免使用繁琐的异步进程间通信通道。相反,您可以直接访问所需的变量和调用函数。
配置
由于单进程模式下只有一个 QML 引擎,该引擎在系统界面和所有应用之间共享,因此当引擎解析导入语句时,会考虑通过例如 am-config.yaml
提供的任何 QML 导入路径。应用清单文件 info.yaml
提供的导入路径只在应用启动后考虑,即使在应用停止后也会加载。
在多进程模式下,仅考虑特定于应用的导入路径。此外,由于容器可能施加的限制以及出于安全考虑,在 info.yaml
文件中不能使用绝对导入路径。
一般来说,在单进程模式下,配置中定义的路径可以提供给 QML 作为绝对路径;但在多进程模式下作为相对路径。
同样地,作为 info.yaml
部分的一部分,自定义的 pluginPath
在单进程模式和多进程模式下的行为有所不同。在多进程模式下,当一个新的过程启动时,新的 pluginPath
可以非常早地添加到 Qt 中,在大多数系统初始化之前。这确保了在 QPluginLoader 使用时,pluginPath
是正确的。相比之下,在单进程模式下,我们需要向已运行的 QApplication 添加额外的 pluginPath
。这种变化是否有效取决于插件是如何加载的:如果 pluginPath
在需要加载新插件时被重新评估。
注意:在单进程模式下,一些配置选项没有作用,例如:quicklaunch
、quicklaunchQml
、crashAction
等。
构建和运行时选项
只要 Qt 的 Wayland 组合模块可用,应用管理器就会构建带有多进程支持。要禁用多进程支持,请显式指定 force-single-process
选项。如果你指定了 force-multi-process
选项,并且组合器不可用,则配置步骤将失败。
如果应用管理器仅支持单进程模式,使用 qml
运行时的 QML 应用始终在系统界面相同的进程中运行。在这种情况下,原生应用被省略,因为它们只能在专用进程中运行。这种差异由入口点强加:具有可执行文件的 native
运行时和拥有主 QML 文件的 qml
运行时。对于后者,应用管理器在多进程模式下提供了可执行文件(《code translate="no">appman-launcher)。
如果应用管理器是用多进程模式构建的,你仍然可以通过在命令行中传递 --force-single-process
来强制它以单进程模式运行。这会导致如上所述的相同运行时行为。即使以多进程模式运行应用管理器,这也并不意味着 QML 应用获得专用进程:如果它们使用 qml-inprocess
运行时,它们将在系统界面内进程中执行。
应用生命周期
需要注意的是,当单进程模式下的应用崩溃时,它会终止整个程序。相比之下,当多进程模式下的应用崩溃时,系统界面和其他应用将继续运行。在多进程模式下,系统界面甚至会在应用崩溃时接收到通知并可以做出反应,例如重新启动应用。
在一个应用程序中使用 QML 单例有一些影响。在 QML 中,单例存在于自己的私有、但全局的上下文中 - 它们甚至在不同的 QML 引擎实例间共享。单例一次性实例化,在首次使用时,只要进程存在就保持状态。这意味着如果应用程序在单进程模式终止,任何已经实例化的单例都将继续存在并保持其当前状态。因此,当应用程序再次启动时,单例的状态可能与需要重新实例化单例的多进程情况不同。
应用程序窗口
窗口的表示方式取决于您是否在单进程或多进程模式下运行应用程序。窗口通过 WindowManager::windowAdded 从应用程序公开至系统用户界面。为了方便并作为 Qt 标准的 qmlscene
和 qml
工具的替代,可以使用纯 QML Windows
或甚至将 Item
作为根元素。但是,如果您的应用程序需要单进程和多进程模式的相似性,则必须使用 ApplicationManagerWindow。此外,使用 ApplicationManagerWindow 也有其他好处,例如窗口属性。
单进程和多进程模式下应用程序窗口之间的某些值得注意的差异是:
- ApplicationManagerWindow 以两种不同的方式公开给系统用户界面。
- 在多进程模式下,窗口内容表面的句柄通过 Wayland 协议在进程边界传递。系统用户界面将此作为表面项接收,该表面项在层次上独立于应用程序的窗口。
- 在单进程模式下,ApplicationManagerWindow 直接将其
contentElement
项提供给系统用户界面。因此,应用程序可以从系统用户界面本身或从任何其他运行的程序访问项,因为它们都在共享相同的 QML 场景。
- 在窗口中定义的某些属性、函数和信号的行为将根据运行模式而有所不同:最重要的是,单进程模式下缺少窗口状态(如最大化或全屏)。请参阅 ApplicationManagerWindow 的文档以获取更多详细信息。
- 焦点处理在两种模式下都相同,但请注意,在单进程模式下,焦点项是在系统用户界面和活动应用程序间共享的。在 6.7 之前,当在应用程序窗口的非激活区域点击/轻触时,焦点不会改变。
- 由于上述属性或方法引起的代码块中的错误将导致后续语句在多进程模式下不再评估;但在单进程模式下并非如此。
输入
由于 Wayland 客户端(应用程序)无法向系统用户界面报告它们是否已接受按键事件等因素,存在一些关于键盘输入的特殊性。在多进程模式下,按键事件将被传递给系统用户界面和应用程序。在单进程模式下也是如此, mutta 如果应用程序接受事件,则系统用户界面将不再收到它。这可以通过使用 Shortcut 或在系统用户界面中安装全局事件过滤器来解决。
资源消耗
在多进程模式下,多核系统上的 CPU 使用效率可能更高,因为操作系统可以调度更多进程,并可能更好地利用核心。
然而,在多进程模式下,每个应用程序的内存消耗比单进程模式更高。GPU需要更多的内存来分配额外的窗口表面缓冲区。此外,包含应用程序资产的纹理不会被共享。如果两个应用程序渲染相同的图像文件,在多进程模式下将创建两个纹理;而在单进程模式下则只有一个。
由于额外的数据结构,CPU 的每个应用程序的内存消耗更高。例如,如果有一个应用程序正在运行,在多进程模式下会有两个 QML 引擎实例:一个用于系统界面,一个用于应用程序。在单进程模式下,由于一切都在系统界面中运行,所以只有一个实例。在多进程模式下,资源也可能被重复。不过,可以通过使用共享图像提供程序或将图像从 CPU 内存中删除(通过 QSG_TRANSIENT_IMAGES 环境变量)来解决这个问题。
另一方面,多进程模式具有一个显著的优势,即不再需要的应用程序可以终止,从而释放它们分配的资源。在单进程模式下,应用程序永远不会真正终止,所以它们的内存不会被释放,导致总的消耗随着每个应用程序的启动而稳步增长,无论它们是否已停止。QML 引擎不允许您卸载对象层次结构的一部分。
一个应用程序中单进程和双进程模式的支持
如果您的应用程序需要支持单进程模式和多进程模式,必须在应用程序和系统界面之间定义一套进程间通信(IPC)接口,并且始终坚持使用它们。考虑将这些接口作为您的审查政策的一部分。虽然您可以使用任何适合您用例的 IPC 机制,但应用程序管理器包含了一个基于 Intents 的 IPC 机制,该机制完全抽象了单进程与多进程的差异。此机制还使得为 QML 开发者创建新接口变得容易。
© 2024 Qt 公司。此处包含的文档贡献归各自所有者所有版权。此处提供的文档根据自由软件基金会发布的 GNU 自由文档许可证 1.3 版本 的条款提供。Qt 和相应的商标是芬兰 Qt 公司及其在全球的子公司和机构的商标。所有其他商标均为各自所有者的财产。