格式化输出:应用接口与后端

本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。

选择输出接口时,应考虑调用上下文、输出设备、是否需要过滤,以及数据是否要延后处理。

接口

头文件

用途与路径

printk

<zephyr/sys/printk.h>

简单诊断输出;可通过配置导入日志系统

printf/snprintf

<stdio.h>

所选 C 库的标准输出或内存格式化

shell_print/error

<zephyr/shell/shell.h>

向指定 Shell 实例输出,与命令交互协调

LOG_*

<zephyr/logging/log.h>

带来源、等级、过滤和后端的日志

cbprintf/snprintfcb

<zephyr/sys/cbprintf.h>

回调格式化或避免引入独立格式化实现

printk

启用 CONFIG_PRINTK 及目标所需的控制台配置。输出位置由架构、控制台驱动和配置决定, 不能从 API 名称推断它一定使用 UART。 CONFIG_LOG_PRINTK 会把 printk 导入日志,延后日志模式中它也可能延后显示。

#include <zephyr/sys/printk.h>

void report_status(int status)
{
    printk("status=%d\n", status);
}

频繁输出会影响处理时间。即使某一输出路径支持 ISR 调用,也不表示任意后端或 任意 C 库 printf 都适合在中断里使用。

标准 C 库输出

Zephyr 可选择不同 C 库,printf 支持的格式与浮点配置、内存使用随之变化。 例如 cbprintf 的浮点选项与某个 libc 的 printf 浮点选项不能直接互换。

优先使用带长度的内存格式化并检查截断:

#include <stdio.h>
#include <errno.h>

int format_status(char *buffer, size_t capacity, int status)
{
    int rc = snprintf(buffer, capacity, "status=%d", status);

    if (rc < 0) {
        return rc;
    }
    if ((size_t)rc >= capacity) {
        return -ENOSPC;
    }
    return 0;
}

snprintf 成功返回原本需要的字符数,不包含结尾 NUL, 返回值大于等于容量表示输出被截断。字符串格式不能来自未经控制的外部输入。

Shell 与日志

Shell 命令回调使用 shell_print(sh, ...)、shell_error(sh, ...), 通常由这些接口追加换行,避免额外重复输出。 日志使用 LOG_* 宏记录来源和等级,生产代码可按模块配置过滤。 它们还需配置合适的传输后端,详见 Shell 系统使用指南 和 日志系统使用指南。

当前 logger 会打包格式串和参数;延后模式把格式化及后端输出安排在后续处理时机。 Shell 与 logger 可以共享服务能力,但不能简单描述为“所有接口最后都走同一个 UART”。 多个后端、日志重定向、不同 libc 和自定义输出钩子都会改变实际路径。

性能与资源

格式转换、消息缓冲、输出带宽和处理线程栈都影响资源。 浮点格式化可能增加代码与栈,长 hexdump 会增加日志缓冲压力。 在实时路径中记录必要信息,将可延后工作放到合适线程,并通过构建配置和测量确定成本。

上游依据