3.3编译Xenomai用户层

3.3 编译Xenomai用户层

3.3.1 构建 Xenomai ARM64 库和工具的示例

以下示例使用以下约定:

  • $xenomai_root:Xenomai 源码目录/root/xenomai/xenomai-3.2.4
  • $build_root:一个干净的构建目录/root/xenomai/xenomai-3.2.4-build
  • $staging_dir:一个将临时保存安装文件的目录xenomai-3.2.4-install

以下命令,可以完成配置、编译及安装。

xenomai_root="/root/xenomai/xenomai-v3.2.4"
build_root="/root/xenomai/xenomai-v3.2.4-build"
staging_dir="/root/xenomai/xenomai-v3.2.4-install"

rm -fr $build_root $staging_dir
mkdir -p $build_root $staging_dir

cd $xenomai_root
./scripts/bootstrap

cd $build_root

$xenomai_root/configure \
--build=i686-pc-linux-gnu \
--host=aarch64-linux-gnu \
--enable-pshared \
--enable-smp \
--with-core=cobalt \
CC=aarch64-linux-gnu-gcc \
LD=aarch64-linux-gnu-ld \
CFLAGS="-march=armv8-a" \
LDFLAGS="-march=armv8-a"

make -j DESTDIR=$staging_dir install

configure配置阶段,使用了针对多核ARM64的典型配置。configure执行完毕后,会自动生成一个头文件include/xeno_config.h,里面定义了和配置相关的宏定义,最终用于控制代码编译和运行。

如果configure执行失败,可以参考其自动生成的config.log,该文件包含在运行 configure 时产生的所有消息,
以便在 configure 出现错误时帮助调试。

完成编译并安装后,可以在安装目录xenomai-v3.2.4-install查看到以下内容。

tree xenomai-v3.2.4-install/ -L 3
xenomai-v3.2.4-install/
└── usr
    └── xenomai
        ├── bin
        ├── demo
        ├── etc
        ├── include
        ├── lib
        ├── sbin
        └── share

对于嵌入式系统来说,将上述usr/xenomai目录完整的拷贝到根文件系统的’/usr’目录即可!

3.3.2 bootstrap生成configure脚本

在软件开发中,特别是在使用 autoconfautomakelibtool 等工具的项目中,bootstrap 脚本通常用于生成 configure 脚本。这个过程也被称为“引导”或“初始化”。

如果您正在从 Xenomai GIT 树(git.xenomai.org)构建源码,则需要在 Xenomai 源码树中生成 configure 脚本和 Makefile。推荐的方法是运行随附的自动重新配置脚本,从源码树的顶部运行./scripts/bootstrap。在执行此脚本之前,需先安装相关依赖。

sudo apt install debhelper findutils autotools-dev autoconf automake libtool pkg-config libltdl-dev fuse

./scripts/bootstrap

如果您从发布 tar 包构建,则提取的源码树中将提供一组由 autoconf 生成的文件,因此不需要重新配置。当运行时,生成的 configure 脚本会为 Cobalt 和 Mercury 核心准备构建库和程序。构建过程中会自动透明地选择可能需要的特定核心代码。

对于本书来说,从 tar 包构建。在上一章节,已经解压xenomai源码包xenomai-3.2.4.tar.bz2,生成了xenomai-3.2.4源码目录。但是,此目录下并未包含configure 脚本,仍然需要使用手动生成。

cd ./xenomai-v3.2.4

./scripts/bootstrap

3.3.3 configure完成配置并生成Makefile

执行./configure --help可以看到完整的帮助信息。本章详细解释各配置的意义。

3.3.3.1 安装目录与程序名称
1. 安装目录
  • –prefix=PREFIX 将架构无关的文件(如头文件、文档、配置文件等)安装在 PREFIX 目录下,默认值[/usr/xenomai]
  • –exec-prefix=EPREFIX 将架构相关的文件(如可执行文件、库文件等)安装在 EPREFIX 目录下,默认值[PREFIX]

默认情况下,make install 将把所有文件安装在 /usr/xenomai/bin/usr/xenomai/lib 等目录下。可以使用 --prefix 指定不同于 /usr/xenomai 的安装前缀,例如 --prefix=$HOME。但是,一般不建议修改PREFIX,同时也不建议把PREFIX和EPREFIX设置不同的值。

对于嵌入式Linux交叉编译而言,可以使用DESTDIR=来设置一个临时保存安装文件的目录。在编译完成后,将目录下内容拷贝到嵌入式Linux根文件系统。

tree xenomai-v3.2.4-install/ -L 3
xenomai-v3.2.4-install/
└── usr
    └── xenomai
        ├── bin
        ├── demo
        ├── etc
        ├── include
        ├── lib
        ├── sbin
        └── share
2. 子目录

如需更加精细地控制子目录,可使用以下选项。

  • --bindir=DIR:用户可执行文件目录 [EPREFIX/bin]
  • --sbindir=DIR:系统管理员可执行文件目录 [EPREFIX/sbin]
  • --libexecdir=DIR:程序可执行文件目录 [EPREFIX/libexec]
  • --sysconfdir=DIR:只读单机数据目录 [PREFIX/etc]
  • --sharedstatedir=DIR:可修改的架构无关数据目录 [PREFIX/com]
  • --localstatedir=DIR:可修改的单机数据目录 [PREFIX/var]
  • --runstatedir=DIR:可修改的每进程数据目录 [LOCALSTATEDIR/run]
  • --libdir=DIR:目标代码库目录 [EPREFIX/lib]
  • --includedir=DIR:C 头文件目录 [PREFIX/include]
  • --oldincludedir=DIR:非 GCC 的 C 头文件目录 [/usr/include]
  • --datarootdir=DIR:只读架构无关数据根目录 [PREFIX/share]
  • --datadir=DIR:只读架构无关数据目录 [DATAROOTDIR]
  • --infodir=DIR:info 文档目录 [DATAROOTDIR/info]
  • --localedir=DIR:区域依赖数据目录 [DATAROOTDIR/locale]
  • --mandir=DIR:man 文档目录 [DATAROOTDIR/man]
  • --docdir=DIR:文档根目录 [DATAROOTDIR/doc/xenomai]
  • --htmldir=DIR:html 文档目录 [DOCDIR]
  • --dvidir=DIR:dvi 文档目录 [DOCDIR]
  • --pdfdir=DIR:pdf 文档目录 [DOCDIR]
  • --psdir=DIR:ps 文档目录 [DOCDIR]
3. 程序名称
  • --program-prefix=前缀:在安装的程序名称前添加前缀
  • --program-suffix=后缀:在安装的程序名称后添加后缀
  • --program-transform-name=程序:对安装的程序名称运行 sed 程序
3.3.3.2 通用配置选项
  • --enable-shared[=PKGS]

    • 构建共享库
    • 默认构建所有共享库
  • --enable-static[=PKGS]

    • 构建静态库
    • 默认值构建所有静态库
  • --disable-demo

    • 禁用演示代码
    • 默认情况下,会构建demo
  • --disable-testsuite

    • 禁用测试套件
    • 默认情况下,构建测试套件
  • --enable-condvar-workaround

    • 启用对 glibc 中优先继承(Priority Inheritance,PI)与条件变量(condvars)问题的解决方法。
    • 对于Cobalt无需启用,默认关闭
  • --enable-lazy-setsched

    • 启用延迟更新调度参数。仅在判断线程处于Relax状态时,立即更新调度参数。
    • 默认关闭,总是立即更新调度参数
  • --with-core=<type>

    • 指定要构建支持库的实时核心,可以是 cobaltmercury
    • 默认为 cobalt
  • --enable-debug[=partial]

    • 如果不使用--enable-debug,则默认情况下会关闭所有debug信息。
    • --enable-debug支持三种模式。当不指定模式的时候,默认时partial模式。
      • symbols:启用调试符号,但仍然开启优化(-O2)。此选项没有开销,适用于在运行应用程序时使用 gdb 快速获取有意义的回溯。
      • partial:包含symbols子集,并且还启用了 Xenomai 代码中的内部一致性检查(主要存在于 Copperplate 层)。它定义了 CONFIG_XENO_DEBUG 宏,适用于 Xenomai 库和从 xeno-config 脚本(即 xeno-config --cflags)获取编译标志的应用程序。部分调试模式隐式地启用了 --enable-assert
      • full:包含partial子集,但禁用了优化(-O0),并且可能执行更多的内部一致性检查。除了 CONFIG_XENO_DEBUG,还定义了 CONFIG_XENO_DEBUG_FULL 宏。此级别引入了最多的开销,可能会使最坏情况下的延迟增加三倍甚至更多。
  • --enable-assert

    • Xenomai 库中包含许多调试断言语句,用于动态检查运行时系统的内部一致性(参见 man assert(3))。
    • 默认值依赖于--enable-debug
  • --enable-pshared

    • 启用后,会定义 CONFIG_XENO_PSHARED 宏。此选项允许不同进程间共享资源,像共享内存、信号量等。在实时系统里,这能让多个进程高效协作,共享数据和状态,减少进程间通信开销,提升系统整体性能和响应速度。启用 --enable-pshared 后,脚本会检查系统是否支持 shm_open 函数,若不支持则报错。
    • 默认情况下,不启用
  • --enable-registry[=/registry-root-path]

    • Xenomai API 可以通过pseudo-filesystem导出其内部状态,可以通过读取这些文件来获取有关现有实时对象的信息,例如任务、信号量、消息队列等。
    • 默认路径为/var/run/xenomai,在其中自动创建//子目录。通过这个路径访问活跃实时对象的内部状态。会话标签<session>是从 –session 运行时开关获取的。如果没有指定会话名称,则会使用 anon@。例如,查看 VxWorks 任务的属性可以按如下方式操作:
      $ cat /var/run/xenomai/root/anon@12656/12656/vxworks/tasks/windTask
      name       = windTask
      errno      = 0
      status     = ready
      priority   = 70
      lock_depth = 0
    
    • 此功能由 FUSE(http://fuse.sourceforge.net/)支持,必须在目标系统上可用。构建 Xenomai 库时需要工具链中提供 FUSE 开发库,并且目标内核中必须启用 CONFIG_FUSE_FS
    • 默认情况下,处于关闭状态
  • --enable-lores-clock

    • 启用低分辨率时钟支持。
    • 默认情况下,低分辨率时钟功能未启用。如果您需要此支持(例如用于 pSOS 或 vxworks API),则可以使用此选项启用。
  • --enable-clock-monotonic-raw

    • Xenomai 库需要底层 PosiX 接口提供一个单调时钟。如果您的系统上可用 CLOCK_MONOTONIC_RAW,则可以传递此开关,否则默认使用 CLOCK_MONOTONIC
    • Cobalt实现了CLOCK_MONOTONIC_RAW,当选择--with-core=cobalt时,此选项默认打开。
  • --enable-tls

    • Xenomai 可以使用 GCC 的线程本地存储扩展(TLS)来加速其内部使用的每线程信息的检索。此开关启用 TLS,使用相反的 --disable-tls 来禁用此功能。
    • 由于某些版本/架构组合的 GCC 存在这个特性的错误,TLS 是否默认启用是架构特定的决定。目前,默认情况下为 x86 和 powerpc 启用此功能,其他架构需要显式传递 --enable-tls 到 configure 脚本。
  • --enable-dlopen-libs

    • 此开关允许程序使用 dlopen(3) 动态加载基于 Xenomai 的库。启用动态加载会引入一些开销,尤其是在启用了 TLS(参见 --enable-tls)时,这可能会根据架构而有所不同。当与 --enable-tls 一起使用时,将自动选择全局动态 TLS 模型。
    • 默认情况下,动态加载基于 Xenomai 的库是禁用的。
  • --enable-async-cancel

    • 启用由实时 API 创建的 Xenomai 线程的完全异步取消功能,并对 Xenomai 实现代码进行相应保护。若禁用此功能,Xenomai 会假定线程仅在到达取消点(如系统调用)时,才会因取消请求而退出。
    • 完全异步取消功能很容易导致资源泄漏、数据静默损坏、安全问题以及各种难以控制的 bug。启用此功能的唯一合理场景是,需要取消那些运行时间极长、无系统调用且无显式退出条件的忙循环线程,不过这种线程的设计或许本身就需要重新审视。
    • 异步取消功能默认处于禁用状态。
  • --enable-smp

    • 该选项用于控制是否启用对称多处理支持。启用 --enable-smp 选项后,Xenomai 系统能充分利用多核 CPU 的优势,将任务分配到不同核心并行处理,提升系统整体性能和响应速度。
    • 默认启用对称多处理支持。
  • --enable-sanity

    • 用于控制运行时健全性检查(sanity checks),支持--enable-sanity=yes-enable-sanity=no
    • 健全性检查是在程序运行过程中对关键数据、状态或操作进行验证,以确保程序运行符合预期,及时发现潜在错误。
    • 默认情况下,CONFIG_XENO_SANITY 变量被设置为 y,意味着运行时健全性检查功能处于启用状态。
  • --enable-fortify

    • 用于控制是否启用 _FORTIFY_SOURCE 功能。_FORTIFY_SOURCE 是 GCC 编译器提供的一种安全特性,能在编译时和运行时检测常见的缓冲区溢出、格式化字符串漏洞等安全问题。

    • 在没有使用此参数的情况下,如果系统libc支持__vfprintf_chk函数,则自动启用_FORTIFY_SOURCE(相当于默认开启)

    • 在运行 ./configure 脚本时,若使用 --enable-fortify 选项且值为 y 或者 yes,启用 _FORTIFY_SOURCE 功能,若检测失败会报错;若值不为 y、yes,禁用该功能。

    • --enable-debug=full,在这种情况下,--enable-fortify 将被忽略。

  • --enable-valgrind-client

    • 用于控制是否启用 Valgrind 客户端 API 支持。在Valgrind上运行Xenomai 3应用程序的功能仅支持Mercury核心。Valgrind 是一款强大的内存调试、内存泄漏检测和性能分析工具,其客户端 API 允许开发者在代码中嵌入特定指令,让 Valgrind 能更深入地理解程序行为,实现更精准的调试和分析。
    • 首先检查系统中是否存在 valgrind/valgrind.h 头文件,如果存在,则将 CONFIG_XENO_VALGRIND_API 设置为 y,表示系统可能支持 Valgrind 客户端 API。
    • 在运行 ./configure 脚本时,如果使用 --enable-valgrind-client=yes (或者不指定该选项,因为默认行为是尝试启用),CONFIG_XENO_VALGRIND_API 会被设置为 y;如果使用 --enable-valgrind-client=no,则会取消设置 CONFIG_XENO_VALGRIND_API 变量,关闭该 API 支持。
  • --enable-doc-build

    • 生成基于 Doxygen 标记语言的内联 Xenomai 文档,作为 PDF 和 HTML 文档。还生成基于 Asciidoc 标记语言的其他文档,如手册页。
    • 默认不构建文档
  • --enable-x86-vsyscall

    • 用于控制在 x86 架构且使用 Cobalt 核心模式时,使用 x86/vsyscall 接口发出系统调用。如果禁用,将使用旧的 0x80 向量。
    • vsyscall(Virtual System Call)是 x86 架构上的一种机制,能让用户空间程序以较低开销发起系统调用,避免了完整软件中断带来的较大开销。
    • 启用此选项需要 NPTL,默认启用。
3.3.3.3 交叉编译选项

为了交叉编译 Xenomai 库和程序,需要向 configure 脚本传递--build--host 选项。

  • --build 此选项用于选择运行编译工具的架构,即运行 configure 脚本的系统。如果不指定,一般来说configure能够自动解析出正确的值。如果是在x86上执行交叉编译:

    • 32位x86: --build=i686-pc-linux-gnu
    • 64位x86_64: --build=x86_64-pc-linux-gnu
  • --host 此选项用于选择要构建库和程序的目标架构。

    • 当向 configure 传递 --host=aarch64-linux 时,它会自动将 aarch64-linux- 作为所有编译工具名称的前缀,并从前缀中推断目标架构名称。例如,64 位 ARM 架构的编译器被推断为 aarch64-linux-gcc
    • 如果实际的交叉编译器与 configure 从前缀中推断的不同,需要在 configure 命令行中手动传递所有编译工具的名称,至少包括 CC 和 LD 变量。
    CC=aarch64-linux-gnu-gcc
    LD=aarch64-linux-gnu-ld
    

与之前的版本不同,Xenomai 不再向 gcc 传递任何特定于 ARM 架构的标志或 FPU 标志,因此用户需要使用 CFLAGS 和 LDFLAGS 变量显式传递这些标志。例如:

CFLAGS="-march=armv8-a"
LDFLAGS="-march=armv8-a"

CFLAGS 和 LDFLAGS 变量如何设置? 首先确定目标ARM64 SOC支持的架构及包含的硬件特性,然后查询gcc手册,确定正确的值。

以Ubuntu22.04为例,其gcc版本为11.3.0

aarch64-linux-gnu-gcc -v
gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)

查询GCC手册https://gcc.gnu.org/onlinedocs/,在aarch64架构的GCC编译器中,-march-mcpu-mtune的作用和关系如下:

1. -march=架构
  • 格式: 指定目标架构的名称,并可选地指定一个或多个特性修饰符。此选项的格式为 -march=arch{+[no]feature}*。feature(功能修饰符)的允许值详见GCC手册中-march 和 -mcpu 功能修饰符子章节的说明。
  • 作用:指定目标架构的版本(如armv8-aarmv8.1-a),确定编译器可使用的指令集和硬件特性。
  • 影响:生成的代码仅兼容指定架构及以上版本,可能无法在更旧的架构上运行。例如,-march=armv8.1-a会启用ARMv8.1-A的指令(如原子操作扩展)。

下表总结了允许的 arch 值及其默认启用的特性:

arch架构默认包含的特性
armv8-aArmv8-A+fp, +simd
armv8.1-aArmv8.1-Aarmv8-a, +crc, +lse, +rdma
armv8.2-aArmv8.2-Aarmv8.1-a
armv8.3-aArmv8.3-Aarmv8.2-a, +pauth
armv8.4-aArmv8.4-Aarmv8.3-a, +flagm, +fp16fml, +dotprod
armv8.5-aArmv8.5-Aarmv8.4-a, +sb, +ssbs, +predres
armv8.6-aArmv8.6-Aarmv8.5-a, +bf16, +i8mm
armv8-rArmv8-Rarmv8-r

native 值在原生 AArch64 GNU/Linux 上可用,使编译器选择主机系统的架构。如果编译器无法识别主机系统的架构,则此选项无效。

2. -mtune=CPU型号
  • 作用:仅优化代码以适应特定CPU的微架构(如指令调度、分支预测),不改变指令集
  • 典型用例:在兼容旧架构(通过-march指定)的同时,为新CPU优化性能。例如:
    -march=armv8-a -mtune=cortex-a76  # 兼容ARMv8-A,但针对A76优化
    

指定 GCC 应针对其优化代码性能的目标处理器名称。此选项允许的值包括:genericcortex-a35cortex-a53cortex-a55cortex-a57cortex-a72cortex-a73cortex-a75cortex-a76cortex-a76aecortex-a77cortex-a65cortex-a65aecortex-a34cortex-a78cortex-a78aecortex-a78caresexynos-m1emagfalkorneoverse-512tvbneoverse-e1neoverse-n1neoverse-n2neoverse-v1neoverse-v2graceqdf24xxsaphiraphecdaxgene1vulcanocteontxocteontx81octeontx83octeontx2octeontx2t98octeontx2t96octeontx2t93octeontx2f95octeontx2f95nocteontx2f95mma64fxthunderxthunderxt88thunderxt88p1thunderxt81tsv110thunderxt83thunderx2t99thunderx3t110zeuscortex-a57.cortex-a53cortex-a72.cortex-a53cortex-a73.cortex-a35cortex-a73.cortex-a53cortex-a75.cortex-a55cortex-a76.cortex-a55cortex-r82cortex-x1ampere1ampere1acobalt-100native

3. -mcpu=CPU型号
  • 格式:指定目标处理器的名称(可选附带一个或多个功能修饰符后缀)。该选项的格式为 -mcpu=cpu{+[no]feature}*,其中:cpu(处理器名称)的允许值与 -mtune 选项支持的处理器名称完全相同。feature(功能修饰符)的允许值详见GCC手册中-march 和 -mcpu 功能修饰符子章节的说明。
  • 作用:指定具体的CPU型号(如cortex-a53neoverse-n1),隐式完成两件事:
    1. 设置架构:根据该CPU支持的架构版本,自动设置-march(例如,cortex-a76对应armv8.2-a)。
    2. 设置优化:等同于-mtune=CPU型号,针对该CPU的微架构进行优化(如流水线、缓存策略)。

推荐实践

  • 若目标CPU明确且在GCC支持列表,优先用-mcpu简化配置,同时定义指令集和优化目标(相当于-march+-mtune)。
  • 若仅能明确CPU兼容架构,建议使用-march
  • 避免-mcpu-march冲突,除非明确架构版本兼容。
  • -mtune:仅定义优化目标,不限制指令集。可单独使用,或与-march/-mcpu组合,不影响指令集。

默认情况:如果未指定 -mtune=-mcpu=-march=,则GCC将保证最大范围目标处理器兼容性。

示例总结

场景选项组合效果
兼容ARMv8-A,针对A76优化-march=armv8-a -mtune=cortex-a76生成ARMv8-A指令,优化A76性能
直接为A76生成代码-mcpu=cortex-a76等价于 -march=armv8.2-a -mtune=cortex-a76
兼容A53指令集,优化A72性能-mcpu=cortex-a53 -mtune=cortex-a72不推荐(可能冲突),应分开指定-march-mtune
### Xenomai 3.2 编译安装教程 对于希望在 Ubuntu 系统上编译并安装 Xenomai 3.2 的用户来说,可以按照如下方法操作: #### 准备工作 确保系统已经更新至最新状态,并安装必要的开发工具和依赖项。可以通过执行以下命令来完成这些准备工作[^1]。 ```bash sudo apt-get update && sudo apt-get upgrade -y sudo apt-get install build-essential linux-source git wget libncurses-dev bison flex libssl-dev dkms kmod -y ``` #### 下载源码 获取 Xenomai 源代码最简单的方式是从官方仓库克隆最新的稳定分支版本。这里假设要下载特定标签 `v3.2` 对应的发布版。 ```bash git clone --branch v3.2 https://github.com/xenomai/xenomai.git xenomai-3.2 cd xenomai-3.2 ``` #### 配置内核支持 为了使 Xenomai 能够正常运行,在此之前还需要准备一个带有实时补丁 (PREEMPT_RT) 的 Linux 内核。这一步骤可能涉及到重新编译内核以启用某些特性选项。如果当前使用的不是预构建的支持 RT 补丁的内核,则需自行处理这部分内容[^2]。 #### 编译与安装 Xenomai 库 一旦完成了上述所有前置条件之后,就可以继续进行 Xenomai 自身的编译过程了。通常情况下,默认配置即能满足大多数需求;如果有特殊定制化的需求,可以在调用 configure 命令前通过修改相应的参数来进行调整。 ```bash ./configure --prefix=/usr/local/xenomai --enable-smp --with-core=cobalt make -j$(nproc) sudo make install ``` #### 设置环境变量 为了让系统能够识别新安装好的 Xenomai 工具链及相关头文件路径,建议编辑用户的 shell profile 文件(如 `.bashrc` 或者 `.zshrc`),添加下面几行语句以便自动加载所需环境设置。 ```bash export PATH=$PATH:/usr/local/xenomai/bin export PKG_CONFIG_PATH=/usr/local/xenomai/lib/pkgconfig:$PKG_CONFIG_PATH export LD_LIBRARY_PATH=/usr/local/xenomai/lib:$LD_LIBRARY_PATH source /etc/profile.d/xenomai.sh ``` 最后重启终端会话或执行 source ~/.bashrc 来应用更改后的环境变量设定。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值