
fluent-bit 内嵌 WAMR 的平台抽象层解析从零移植到新操作系统的完整指南【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本指南以 WAMRWebAssembly Micro Runtime在 fluent-bit 仓库中内嵌的core/shared/platform平台抽象层为核心讲解 WAMR 如何通过统一 API 屏蔽操作系统差异并给出将 WAMR 移植到全新操作系统如自研 RTOS、裸机环境的完整操作路径。读完本文你将掌握平台抽象层的目录结构与 API 契约、platform_api_vmcore.h与platform_api_extension.h两套头文件的实现要点、基于 CMake 的移植接入方式以及复用 POSIX/数学库公共实现来大幅降低移植工作量的技巧。背景为什么 fluent-bit 仓库里有一个 WAMR当前仓库是 Fluent Bit面向 Linux、BSD、macOS、Windows 的轻量级日志、指标与追踪处理器。它通过 filter_wasm 插件 支持使用 WebAssembly 编写过滤器逻辑而该插件依赖的 WASM 运行时正是仓库 lib/wasm-micro-runtime-WAMR-2.4.1/ 目录下的 WAMRIntel 开源的嵌入式 WebAssembly 运行时。在 plugins/filter_wasm/CMakeLists.txt 中可以确认这一依赖关系插件源码直接 include WAMR 的core/iwasm/include头文件并链接flb-wasm-static与vmlib-static两个静态库目标。WAMR 之所以能同时运行在桌面系统、嵌入式 Linux、RTOS 乃至裸机环境关键就在于core/shared/platform这一层精心设计的平台抽象层Platform Abstraction Layer。平台抽象层结构与已支持平台core/shared/platform/README.md 开门见山地说明了这层目录的定位This folder contains the platform abstract layer for multiple platforms. To support a new platform, you can simply create a new folder here and implement all the APIs defined inincludefolder.也就是说WAMR 运行时的核心代码解释器、AOT、WASI 等只与抽象 API 打交道所有系统相关的行为内存、线程、时间、文件、socket都下沉到平台目录中按平台实现。当前仓库中已经内置了 15 个平台的实现目录见lib/wasm-micro-runtime-WAMR-2.4.1/core/shared/platform/平台目录面向的系统linux/通用 Linux含 Android 之外的大多数 POSIX 场景android/Androiddarwin/macOS / iOSfreebsd/FreeBSDwindows/Windowslinux-sgx/基于 SGX 的机密计算环境zephyr/、nuttx/、riot/、rt-thread/、alios/、ego/、esp-idf/、vxworks/、cosmopolitan/各类 RTOS / 嵌入式 / 异构运行时环境除平台目录外还有三个共享目录include/平台抽象层的接口契约即所有平台都必须实现或按需实现的 API 声明common/跨平台可复用的公共实现包括posix/POSIX 兼容实现、math/针对缺数学函数的平台、memory/mremap 回退实现、libc-util/libc 辅助工具每个平台目录下的shared_platform.cmake平台 CMake 接入脚本。移植第一步实现平台 API 层按照 doc/port_wamr.mdWAMR 官方移植指南README 中直接推荐参考的指引移植的第一步是在core/shared/platform下为你的新平台以 new-os 为例创建目录并实现include中定义的全部 API。对于可以回馈上游的通用平台直接在仓库内创建core/shared/platform/new-os目录即可对于企业内部不便公开的平台官方建议把平台实现放到 WAMR 仓库之外例如独立仓库维护两者对 API 实现的要求完全一致。必须提供的两个文件在新平台目录中至少需要提供platform_internal.h平台私有头文件用于承载平台特有的宏、数据类型与内部 API。它是include下各头文件的最终依赖platform_common.h、platform_api_vmcore.h、platform_api_extension.h都会#include platform_internal.h因此移植时通常先从定义这个文件开始。参考实现见 linux/platform_internal.h它自己会先定义BH_PLATFORM_LINUX宏。shared_platform.cmake平台的 CMake 接入脚本会被 WAMR 顶层构建脚本 include。官方建议在其中添加平台宏定义例如add_definitions(-DBH_PLATFORM_YOUR_NAME)以 Linux 的 shared_platform.cmake 为模板一个典型实现还包含把平台目录与../include加入头文件搜索路径、include 公共子模块的 cmake、GLOB 收集平台源码文件并合并进PLATFORM_SHARED_SOURCE变量。Linux 版本的核心逻辑如下节选set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) add_definitions(-DBH_PLATFORM_LINUX) include_directories(${PLATFORM_SHARED_DIR}) include_directories(${PLATFORM_SHARED_DIR}/../include) include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake) file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_POSIX_SOURCE})必须实现的 APIplatform_api_vmcore.hplatform_api_vmcore.h 是vmcore纯运行时内核构建所必需的头文件也是最核心的移植契约。它分为两节Section 1运行时必需的接口bh_platform_init/bh_platform_destroy、os_malloc/os_realloc/os_free、os_printf/os_vprintf、os_time_get_boot_us、os_time_thread_cputime_us、os_self_thread、os_thread_get_stack_boundary、os_thread_jit_write_protect_np、os_mutex_init/destroy/lock/unlock。要点bh_platform_init()会被wasm_runtime_init()与wasm_runtime_full_init()调用用于初始化平台内部资源成功返回 0对应的bh_platform_destroy()由wasm_runtime_destroy()调用。内存分配三个函数在未启用系统分配器Alloc_With_System_Allocator时可以简单返回 NULL头文件注释明确说明了这一自由度。os_self_thread()为可选实现仅用于日志os_thread_get_stack_boundary()用于运行时检测原生栈溢出若实现困难可返回 NULL但头文件同时提醒可能存在潜在问题。Section 2WAMR AOT 编译支持所需的接口。若你的移植目标是纯解释器mini product 只需 vmcore这部分 API 仅在使用 AOT 时才需要实现。包括os_mmap/os_munmap/os_mprotect/os_mremap以及内存保护模式枚举MMAP_PROT_NONE/READ/WRITE/EXEC与标志MMAP_MAP_NONE/32BIT/FIXED。头文件中还内联提供了os_mremap_slow()的通用回退实现新映射一块内存、复制旧数据、再释放旧映射。os_dcache_flush()某些 CPU 上 AOT 重定位后的代码可能未写回数据缓存需要实现数据缓存刷新不需要则留空。os_icache_flush()指令缓存刷新。若启用双总线镜像WASM_MEM_DUAL_BUS_MIRROR还需实现os_get_dbus_mirror()。按需实现的扩展 APIplatform_api_extension.hplatform_api_extension.h 是app-mgr 与 app-framework 构建所必需的扩展接口。若目标平台不需要 app-mgr/app-framework则其中 API 可以不必实现这一点在官方移植指南中已明确说明。它包含两大块多线程支持Section 1os_thread_create、os_thread_create_with_prio、os_thread_join、os_thread_detach、os_thread_exit、os_thread_env_init/destroy/inited、os_usleep、os_recursive_mutex_init、条件变量os_cond_*系列、读写锁os_rwlock_*系列、POSIX 风格信号量os_sem_*系列以及用于唤醒阻塞线程的os_blocking_op_init/os_begin_blocking_op/os_end_blocking_op/os_wakeup_blocking_op。头文件注明构建 vmcore 时仅当启用多线程才需要实现构建 app-mgr/app-framework 则必须实现。值得注意的细节头文件中为os_atomic_thread_fence提供了基于 GCC/Clang 编译器特性的自适应回退定义从 GCC 4.9 的__atomic_thread_fence到 C11stdatomic.h的atomic_thread_fence都能自动适配。Socket 支持Section 2os_socket_create、bind、listen、accept、connect、recv、send、recv_from、send_to、close、shutdown、inet_network、addr_resolve以及一系列选项设置/查询 API超时、keep-alive、reuse_addr/port、linger、TCP_NODELAY、TCP_QUICKACK、TCP Fast Open、TCP keepalive 参数、IP 组播等。头文件注明这些 API 仅源码调试source debugging功能需要不需要该功能则无需实现。复用公共实现减少移植工作量官方移植指南特别强调了两处可直接复用的公共实现common/posix/如果目标平台支持 POSIX API可以直接复用该目录下的实现。lib/wasm-micro-runtime-WAMR-2.4.1/core/shared/platform/common/posix/中提供了posix_malloc.c、posix_thread.c、posix_time.c、posix_clock.c、posix_file.c、posix_socket.c、posix_sleep.c、posix_blocking_op.c、posix_memmap.c等文件Linux 平台正是通过 include platform_api_posix.cmake 复用的。该 cmake 脚本还会按构建选项裁剪源码未启用 WASIWAMR_BUILD_LIBC_WASI ! 1时排除posix_file.c与posix_clock.c未启用 WASI 且未启用调试解释器WAMR_BUILD_DEBUG_INTERP时排除posix_socket.c同时通过check_symbol_exists(mremap sys/mman.h MREMAP_EXISTS)探测系统是否支持 mremap不支持时自动 includecommon/memory/的软件回退实现。common/math/ZephyrOS 等平台不提供sqrt、fabs、isnan等数学函数此时应把platform/common/math下的源码见 math.c纳入构建。移植第二步为平台创建 mini product 并构建验证第二步是创建一个只含 vmcore 的最小产品mini product用于验证平台移植是否可用。若目标平台不需要 mini product此步可跳过。创建 product-mini 目录在product-mini/platforms/new-os目录下创建 CMakeList.txt 与 C 实现直接参照 Linux 平台的 mini product。然后通过 CMake 变量WAMR_BUILD_PLATFORM指定目标平台mkdir build cd build cmake .. -DWAMR_BUILD_PLATFORMnew-os也可以在 mini product 的 CMakeList.txt 文件内设置该变量。平台实现位于仓库之外时的处理如果平台实现放在 WAMR 仓库之外例如企业内部平台还需要额外提供SHARED_PLATFORM_CONFIG指向平台自己的shared_platform.cmakecmake .. -DWAMR_BUILD_PLATFORMnew-os -DSHARED_PLATFORM_CONFIG/path/to/new-os/shared_platform.cmakemini product 中的 main 函数负责加载一个 WASM 文件并用运行时执行它这是对平台 API 层最直接的冒烟测试。更多构建配置与参数说明可参考 WAMR 的 build_wamr.md同位于doc/目录与 port_wamr.md 配套。从源码理解平台 API 与运行时的协作方式阅读 platform_common.h 可以进一步理解平台层的公共约定它统一了基础类型uint8/uint16/uint32/uint64、int8/.../int64、float32/float64、定义了BH_MALLOC/BH_FREE默认映射到os_malloc/os_free、提供了跨编译器的 PRI/SCN 格式化宏、BH_MAX_THREAD32、BHT_OK/BHT_ERROR/BHT_TIMED_OUT/BHT_WAIT_FOREVER等错误码约定并对缺失的true/false/inline/NAN/offsetof做兼容兜底。这些约定保证了上层代码书写风格与编译器无关是抽象层能够成立的基础。从调用关系看bh_platform_init是运行时初始化的入口依赖os_*系列是运行时与系统交互的全部通道——上层无论是解释器分配内存、AOT 加载可执行代码还是线程调度、时间戳获取最终都归结到这些平台函数。因此移植是否成功本质上是这组 API 契约是否被完整、正确地满足。在当前仓库中的落地关联虽然 WAMR 平台层本身是跨项目复用的通用组件但在本仓库中可以找到它的实际消费者filter_wasm插件将 WASM 过滤器程序加载进 WAMR 运行时执行其构建依赖 WAMR 的 vmcore 静态库vmlib-static。这意味着当 Fluent Bit 被交叉编译到新的嵌入式平台时WAMR 平台抽象层的移植质量会直接影响filter_wasm能否在该平台稳定运行——线程栈边界检测os_thread_get_stack_boundary关乎 WASM 宿主栈溢出保护内存映射 API 关乎 AOT 代码加载时间 API 关乎日志时间戳的正确性。移植清单快速自检完成移植后建议按以下清单逐项核对platform_internal.h是否存在平台宏BH_PLATFORM_*是否定义shared_platform.cmake是否 include 了../include头文件路径是否将源码加入PLATFORM_SHARED_SOURCE是否实现了platform_api_vmcore.h的全部声明至少 Section 1AOT 场景需含 Section 2 的 mmap 与 cache flush 系列若需要多线程/app-mgr/app-framework是否实现platform_api_extension.h的线程、条件变量、信号量、socket 系列能复用common/posix或common/math的部分是否已通过 cmake include 接入是否通过WAMR_BUILD_PLATFORM必要时加SHARED_PLATFORM_CONFIG成功构建 mini product 并跑通一个 WASM 用例。遵循上述步骤一个具备基础 POSIX 环境的新系统通常可以在复用它人实现的基础上快速完成 WAMR 移植对于无 POSIX 的深度嵌入式平台则按 API 契约逐项实现即可。相关官方文档入口平台抽象层说明见 platform/README.md详细移植步骤见 doc/port_wamr.md构建参数说明见 doc/build_wamr.md。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考