overview of major emabedded linux software stacks

overview of major emabedded linux software stacks

D-Bus

D-Bus是什么?

D-Bus是一种应用程序之间进行通信的消息总线进程间通信(interprocess communication,即IPC)系统。

D-Bus架构图:

diagram

  • 面向消息的中间件机制,允许在同一台机器上同时运行的多个进程之间进行通信
  • 依靠守护进程在应用程序之间传递消息
  • 主要由系统守护进程使用,为客户端应用程序提供服务
  • 示例:以 root 身份运行的网络配置守护程序提供 D-Bus API,CLI 和 GUI 客户端可以使用它来
    配置网络
  • 多条总线
    • 一条系统总线,所有用户均可以访问,用于系统服务
    • 一条会话总线,供每个登录用户使用
  • 对象模型:interface、object、method、signal

一个很典型的蓝牙应用:BlueZ,就是基于D-Bus实现多个客户端与bluetoothd通信。

以BlueZ项目,对D-Bus的一些概念进行简单的说明:

BlueZ项目提供关键的两个应用是:bluetoothd 和 bluetoothctl。

bluetoothd应用连接dbus-daemon,在dbus上注册bus name为 org.bluez 的服务, 紧接着注册object path name 为 /org/bluez/hci0 的对象路径,并在该对象路径下注册interface name 为 org.bluez.Adapter1 的接口,该接口下绑定了方法和属性。

bluetoothctl应用连接dbus-daemon,接着就可以向 org.bluez/org/bluez/hci0org.bluez.Adapter1 下的 StartDiscovery 方法发送请求。

image-20241009193405276

D-Bus API接口

systemd

systemd是什么?

在基于UNIX的计算机操作系统中,init 是操作系统启动期间启动的第一个进程。init 是一个守护进程,它会持续运行直到系统关闭。它是所有其他进程的直接或间接祖先,并自动接收所有孤儿进程。在Linux系统中,进程的结构也是呈现树形,启动第一个进程就是 init (根),它的进程ID号是 1。

上一代关于初始化程序是SysV init 或 BSD init,而现在是Systemd。

  • 几乎所有 Linux 桌面/服务器发行版都使用现代 init 系统,即systemd

  • systemd比 Busybox init 复杂得多,但也功能更强大

  • 仅支持glibc,不支持 uClibc 和 Musl

  • 提供如下功能:

    • 并行启动服务,同时考虑依赖关系
    • 服务监控
    • 通过套接字激活按需启动服务
    • 服务的资源管理:CPU限制、内存限制
  • 基于单元的配置文件

    • 声明性语言,而不是其他 init 系统中使用的 shell 脚本
  • 其他

    • journald:日志daemon,替换了syslogd

    • networkd:用于网络配置管理

    • udevd:热插拔和 /dev 管理

    • logind:登录管理

    • systemctl:控制和监控 systemd 的工具

    • other

基于单元的配置文件

示例1:/etc/systemd/system/sshd.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service

示例2:/usr/lib/systemd/system/wpa_supplicant.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=WPA supplicant
Before=network.target
After=dbus.service
Wants=network.target

[Service]
Type=dbus
BusName=fi.w1.wpa_supplicant1
ExecStart=/usr/sbin/wpa_supplicant -u

[Install]
WantedBy=multi-user.target
Alias=dbus-fi.w1.wpa_supplicant1.service

systemctl

  • systemctl status 查询所有服务的状态
  • systemctl status <service> 查询指定服务的状态
  • systemctl [start|stop|restart] <service> 启动或停止或重启指定服务
  • systemctl [enable|disable] <service> 启用或禁用指定服务开机自启动
  • systemctl is-enabled <service> 查看指定服务是否开机启动
  • systemctl daemon-reload 刷新service配置文件生效
  • systemctl list-units 以表格形式打印所有可用的服务单元

journalctl

journalctl 是用来查询systemd-journald 服务收集到的日志的工具。

  • journalctl -a 查询所有日志
  • journalctl -f 显示最后一个日志,并且实时打印新增的日志
  • journalctl -u <unit_name> 显示指定服务单元的日志

示例1:查询wpa_supplicant.service的日志

1
2
3
4
5
6
7
8
9
10
11
12
$ journalctl -f -u wpa_supplicant.service
Oct 31 05:43:27 homeassistant systemd[1]: Starting WPA supplicant...
Oct 31 05:43:27 homeassistant wpa_supplicant[6665]: Successfully initialized wpa_supplicant
Oct 31 05:43:27 homeassistant systemd[1]: Started WPA supplicant.
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: p2p-dev-wlan0: CTRL-EVENT-DSCP-POLICY clear_all
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: p2p-dev-wlan0: CTRL-EVENT-DSCP-POLICY clear_all
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: nl80211: deinit ifname=p2p-dev-wlan0 disabled_11b_rates=0
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: wlan0: CTRL-EVENT-DSCP-POLICY clear_all
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: wlan0: CTRL-EVENT-DSCP-POLICY clear_all
Oct 31 05:43:48 homeassistant wpa_supplicant[6665]: nl80211: deinit ifname=wlan0 disabled_11b_rates=0
Oct 31 05:44:17 homeassistant systemd[1]: wpa_supplicant.service: Deactivated successfully.

linux graphics stack overview

image-20241008192139617

display controller support

fddev 是一个 Linux 子系统,用于在计算机显示器上(通常在系统控制台上)显示图形。不过已经被弃用了,但仍有一些旧的图形驱动程序仅在此子系统中可用。

DRM 是Linux 内核的一个子系统,负责与现代显卡的GPU进行交互。

支持 SoC 或显卡的显示控制器,以及所有类型的显示面板和桥接器:并行、LVDS、DSI、HDMI、DisplayPort 等。当然,也支持通过I2C或者SPI连接的小型显示面板。设备在linux系统中暴露出来的路径为:/dev/fri/cardX

DRM对应的库:libdrm,提供了一个好用的测试工具:modetest。

GPU support: OpenGL

OpenGL是什么?

  • 开源

    • OpenGL是DRM 子系统中的内核驱动程序,用于向 GPU 发送命令并管理内存。

    • mesa3d 用户空间库实现了各种 OpenGL API,包含大量GPU 特定逻辑

    • 支持越来越多的GPU

  • 所有权

    • 许多嵌入式 GPU 过去仅通过专有 blob 获得支持 –> 长期维护问题
    • 供应商提供的内核驱动程序 –> 如果用户空间是闭源的,则上游不会接受它们
    • 一个(巨大的)闭源用户空间二进制 blob,实现各种 OpenGL API

Concept of display serviers

  • Linux 内核不处理应用程序之间的显示和输入设备的多路复用

    • 只有一个用户空间应用程序可以使用显示器和一组给定的输入设备
  • 显示服务是特殊的用户空间应用程序,它由如下显示/输入复用构成

    • 允许多个客户端 GUI 应用程序提交其窗口内容
    • 根据应用程序提交的内容、窗口可见性和分层,组成屏幕上可见的最终帧
    • 根据焦点将输入事件传播到适当的客户端

X11 and X.org

X.org是什么?

  • X.org是UNIX系统的历史显示服务,包括Linux系统

  • X11协议被用于客户端和服务器结构

    • 本地客户端使用UNIX套接字,远程客户端使用TCP
  • 在现代 Linux 上,在 DRM 或 fbdev 之上处理图形,输入子系统处理输入事件

  • 仍保留,但已是遗留

  • X11许可

Wayland

Wayland是什么?

  • 指定显示服务器与其客户端之间通信的通信协议,以及该协议的 C 库实现
  • 使用 Wayland 协议的显示服务称为 Wayland 合成器
  • X11 协议的现代替代品
  • 更多地基于 OpenGL 技术

Wayland compositors

  • Weston
  • Mutter:被 GNOME 桌面环境使用
  • wlroots:一个 Wayland 合成器库
    • Cage
    • swayWM

Concept of graphics toolkits

  • X11 和 Wayland 协议是非常低级的协议

  • 虽然可以使用X11和wayland,但直接使用这些协议或相应的客户端库开发应用程序会很麻烦

  • toolkits工具

    • 其中一些只能在显示服务上运行:X11 或 Wayland
    • 其中一些可以直接在 DRM + 输入 之上工作,适用于单个全屏应用程序
  • 面向小部件的工具包,具有用于创建窗口、按钮、文本字段、下拉列表等的 API

  • 面向游戏/多媒体的工具包,没有预定义的小部件 API

Qt

Qt是什么?

  • 非常受欢迎且文档丰富的开发框架,提供如下:
    • 核心库:数据结构、事件处理、XML、数据库、网络等
    • 图形库:小组件和其他
  • 标准 API 是 C++,但可以绑定到其他语言
  • 可以作为:
    • 具有 DRM 和 OpenGL 的单个应用程序,或没有加速的 fbdev
    • X11 或 Wayland 上的多个应用程序
  • 多平台:Linux、MacOS、Windows
  • 许可有点复杂,混合了 LGPLv3、GPLv2、GPLv3 和(昂贵的)商业许可

Gtk

Gtk是什么?

  • 作为 GNOME 桌面环境基础的工具包,GNOME 桌面环境是 Linux 桌面发行版中最流行的桌面环境,但在嵌入式项目中逐渐失去吸引力

  • 由 glib(核心库)、pango(文本处理)、cairo(矢量图形)、gtk(小组件库) 组成

  • C 中的标准 API,但许多语言都存在绑定

  • 需要显示服务支持:X11 或 Wayland

  • LGPLv2许可

  • 当前最流行的开发版本是v 3.x,接下来的版本是v 4.x

  • 多平台:Linux、MacOS、Windows

Flutter

Flutter是什么?

  • 跨平台 UI 应用程序开发:Linux、Android、iOS、Windows、MacOS
  • 由Google负责开发和维护
  • 应用开发必须使用 Dart 编程语言
  • 应用程序可以在 Dart 虚拟机中运行,也可以进行本地编译以获得更好的性能
  • BSD-3-Clause认证许可

SDL

  • 跨平台开发库,旨在提供对音频、键盘、鼠标、操纵杆和图形硬件的低级访问
  • 使用C语言实现,轻量级
  • 没有提供小组件库
  • 游戏、媒体播放器、自定义 UI
  • zlib认证许可

Other graphical toolkits

  • Enlightenment Foundation Libraries (EFL) / Elementary
    • 轻量且强大,但不是那么流行
    • 运行在X11 或 Wayland之上
    • LGPLv2.1认证
  • LVGL
    • 非常轻量,主要用于微控制器,但也能运行在Linux上
    • MIT认证许可

Linux multimedia stack overview

image-20241009151839214

Audio stack

  • 内核侧:ALSA子系统,Advanced Linux Sound Architecture
    • 包括音频接口和音频编解码器的驱动程序
    • 暴露的音频设备接口 /dev/snd/
  • 用户空间库:alsa-lib
  • 音频服务
    • 当多个应用程序共享音频设备时需要:混合音频流,将音频流从特定应用程序路由到特定设备
    • JACK:主要用于专业音响
    • pulseaudio:主要用于常规桌面 Linux 音频
    • pipewire:pulseaudio 和 JACK 的现代替代品,已被一些 Linux 发行版采用

Video stack

  • 内核侧:Video4Linux 子系统(简称V4L)
    • 支持摄像头设备:网络摄像头以及 SoC 和摄像头传感器的摄像头接口(并行、CSI 等)
    • 还用于支持视频编码/解码硬件加速器:H264、H265等
    • 暴露的视频设备接口 /dev/videoX
  • 传统用户空间库:libv4l
  • 新的用户空间库,更现代,具有更多功能,正在采用:libcamera
  • 许多多媒体堆栈/软件都支持:GStreamer、ffmpeg、VLC 等

GStreamer

Gstreamer是什么?

  • 用于构建媒体处理组件图表的库
  • 允许创建管道来转换、转变、流式传输、显示、捕获多媒体流(包括音频和视频)
  • 由大量插件组成:视频捕获/显示、音频捕获/播放、编码/解码、缩放、过滤等
  • 一个有趣的替代方案是 ffmpeg

Linux networking stack

image-20241009153641765

Web accessible UI

  • 在嵌入式系统中,使用 Web 界面进行设备配置/监控非常常见
  • 需要 web 服务器:Busybox httpd可以满足简单的需求、lighttpd、nginx、apache可以满足复杂的需求
  • 可以使用 PHP、NodeJS 或其他解释型语言,或者简单的 CGI shell 脚本

Web browsers: rendering engines

向你的设备添加 HTML 呈现功能:

  • WebKit
    • 由Apple发起,在 iOS 和 Safari 中被使用
    • 开源项目许可:LGPLv2.1 和 BSD-2-Clause
    • 在Gtk中集成方式:WebKitGtk
    • 在Qt中的集成方式:QtWebKit
    • 针对嵌入式设备优化的端口:WPE WebKit
  • Blink
    • 从WebKit中分支出来的
    • 由Google开发,并被用在Chrome中
    • 在Qt中的集成方式:QtWebEngine
    • 被 Electron 使用

Web-based UIs

  • 原生 GUI 应用程序的替代方案是创建基于 Web 技术的 GUI

  • 全屏运行 Web 浏览器,并使用流行的 Web 技术开发应用程序

  • 一些可用选项:

    • Cog:适用于 WPE Webkit 端口的简单启动器
    • Electron:将 NodeJS 应用程序与 Web 渲染引擎打包成一个独立应用程序的方法
  • 注意占用空间和性能影响:Web 渲染引擎是一个庞大且耗费资源的软件

Programming languages

  • 可用的语言和框架种类繁多,不仅限于 C/C++
  • 注意空间和性能的影响
  • 编译型语言
    • C/C++
    • Rust
    • Go
    • Ada
    • Fortran
  • 解释型语言
    • Python
    • Javascripts,NodeJS
    • Lua
    • Shell scripts
    • Perl,Ruby,PHP