Newlib

Newlib 是面向嵌入式系统的完整 C 库实现,属于独立开源项目,Zephyr 不包含其源代码。Zephyr SDK 则为每种受支持的架构提供预编译库(libc.a 和 libm.a)。

备注

GNU Arm Embedded 等第三方工具链也附带预编译形式的 Newlib。

Zephyr 实现了由 Newlib 标准 C 库函数调用的“API 钩子”函数。这些函数位于 lib/libc/newlib/libc-hooks.c,将库内部系统调用转换为等效的 Zephyr API 调用。

Newlib 类型

Zephyr SDK 中的 Newlib 有 full(完整)和 nano(精简)两个变体。

完整 Newlib

Newlib 完整变体(libc.a 和 libm.a)是 Zephyr SDK 中功能最齐全的 Newlib 变体,支持几乎所有标准 C 库功能。它优先优化性能而非代码体积,因此占用显著大于 nano 变体。

在应用配置文件中选择 CONFIG_NEWLIB_LIBC,并取消选择 CONFIG_NEWLIB_LIBC_NANO,即可启用此变体。

精简 Newlib

Newlib nano 变体(libc_nano.a 和 libm_nano.a)针对体积优化,支持完整变体的全部功能,但不支持 C99 新增的格式说明符,例如 char 和 long long 类型的格式说明符,即 %hhX 和 %llX。

在应用配置文件中选择 CONFIG_NEWLIB_LIBC 和 CONFIG_NEWLIB_LIBC_NANO,即可启用此变体。

注意,并非所有架构都提供 Newlib nano 变体。是否可用由 CONFIG_HAS_NEWLIB_LIBC_NANO 指定。

格式化输出

Newlib 支持所有标准 C 格式化输入输出函数,包括 printf、fprintf、sprintf 和 sscanf。

Newlib 格式化输入输出实现支持 C 标准定义的所有格式说明符,但有以下例外:

动态内存管理

Newlib 实现了内部堆分配器,用于管理标准动态内存管理接口(例如 malloc() 和 free())使用的内存块。

不同 Newlib 类型的内部堆分配器可能不同。例如,Zephyr SDK 的完整 Newlib(libc.a 和 libm.a)向操作系统请求更大的内存块,其最低内存需求显著高于精简 Newlib(libc_nano.a 和 libm_nano.a)。

Newlib 动态内存管理函数与 Zephyr 侧 libc 钩子之间的唯一接口是 sbrk(),Newlib 通过它管理为内部堆分配器保留的内存池大小。

Newlib 的内存池大小变更请求由 _sbrk() 钩子处理(实现于 libc-hooks.c),该钩子在系统内存不足时返回错误,确保内部堆分配器的内存池不超出可用空间。

启用用户空间时,Newlib 内部堆分配器的内存池放在名为 z_malloc_partition 的专用内存分区中,供用户模式线程访问。

Newlib 堆的可用内存空间取决于系统配置:

Newlib 实现的标准动态内存管理接口是线程安全的,允许多个线程同时调用。