Zephyr学习 第四章 -2:初始化 level、priority 与启动顺序
04-2初始化 level、priority 与启动顺序验证方式SYS_INIT()、device init、ELF/map、native_sim/native/64验证结论源码确认 编译确认 模拟确认1. 本节目标上一节确认 device init 会在main()前执行。本节进一步回答Zephyr 有哪些初始化 level同一个 level 内priority 如何决定顺序SYS_INIT()与 device init 是否使用同一套基础设施驱动为什么不能随便选择一个更早的 level本节最终验证的时间线EARLY - PRE_KERNEL_1 - PRE_KERNEL_2 - POST_KERNEL - APPLICATION - main2. Zephyr 的初始化基础设施本地源码zephyr/include/zephyr/init.hZephyr 使用同一套 init entry 基础设施支持SYS_INIT 注册的系统初始化函数 DEVICE_DT_DEFINE 注册的设备初始化函数init entry 的核心结构structinit_entry{unioninit_function init_fn;union{conststructdevice*dev;/* 可选 mutable device */};};其中union init_function能保存两种签名int(*sys)(void);int(*dev)(conststructdevice*dev);所以SYS_INIT callback 没有 device 参数 device init callback 接收对应 struct device *源码确认3. 初始化 level 总览本地init.h按顺序定义level执行阶段主要限制/用途EARLY刚进入 C 环境后的极早期架构、SoC 极早期设置系统服务不可假设可用PRE_KERNEL_1kernel 初始化上下文使用 interrupt stackkernel services 尚不可用PRE_KERNEL_2仍在 pre-kernel 上下文与 PRE_KERNEL_1 相同限制但阶段更晚POST_KERNELkernel 已可用可以使用 kernel primitives常用于普通 device driverAPPLICATIONmain()之前应用/子系统级初始化SMPSMP 专用阶段仅在CONFIG_SMP启用时可用本次native_sim没有验证 SMP 阶段因此实验只覆盖到APPLICATION。4. EARLY 阶段为什么要非常谨慎EARLY发生在系统启动的最前面。通常不应假设下面内容已经可用schedulersemaphore、mutexheaplogging backend普通 device object readyconsole driver 已完成初始化。本实验的 EARLY callback 只做boot_events[boot_event_count]EARLY:50;即只修改已经清零的静态 RAM不调用printk()从而避免依赖早期 console。5. PRE_KERNEL_1 与 PRE_KERNEL_2本地源码说明这两个阶段运行在 kernel initialization context 使用 interrupt stack kernel services 尚不可用因此 pre-kernel init 不适合阻塞等待 semaphore创建依赖 scheduler 的工作睡眠依赖普通 POST_KERNEL device使用尚未初始化的子系统。两个 level 的区别主要是全局顺序所有 PRE_KERNEL_1 都早于 所有 PRE_KERNEL_2即使PRE_KERNEL_1 priority 99 PRE_KERNEL_2 priority 0前者仍先执行因为 level 排序优先于 priority。6. POST_KERNEL本地定义Executed after Kernel is alive. From this point on, Kernel primitives can be used.普通传感器、总线和外设驱动经常使用POST_KERNEL因为初始化中可能需要semaphore、mutex 等内核对象已初始化的父总线 device日志或较完整的系统服务设备依赖检查。本节伪驱动使用DEVICE_DT_INST_DEFINE(...,POST_KERNEL,50,...)7. APPLICATIONAPPLICATIONinit 在应用main()前执行。适合应用级注册订阅系统事件在 main 前完成的子系统设置不属于具体 device object 的初始化逻辑。实验SYS_INIT(trace_application_20,APPLICATION,20);最终记录证明APPLICATION:20 早于 main8. priority 的规则priority 范围0 ... 99同一个 level 内数值越小 - 越早执行 数值越大 - 越晚执行例如POST_KERNEL priority 10 POST_KERNEL priority 50 POST_KERNEL priority 90顺序为10 - 50 - 90注意这与之后学习的 thread priority 不是同一套对象。这里只讨论启动 init entry 的链接排序。9. level 比 priority 更高一级错误理解priority 0 永远比 priority 99 早正确理解先按 level 排序 再在同一个 level 内按 priority 排序例如PRE_KERNEL_2:99 仍早于 POST_KERNEL:0可以把完整排序 key 简化理解为(level ordinal, priority, sub-priority)10. priority 必须是可用于 section 名的值SYS_INIT()文档要求 priority 是无前导零、无符号的十进制整数 literal或展开为这种整数的 symbolic name/Kconfig symbol。可以SYS_INIT(foo,POST_KERNEL,32);#defineMY_INIT_PRIORITY32SYS_INIT(foo,POST_KERNEL,MY_INIT_PRIORITY);不可以SYS_INIT(foo,POST_KERNEL,CONFIG_KERNEL_INIT_PRIORITY_DEFAULT5);原因是 priority 被拼进 linker section 名普通 C 算术表达式无法在这个位置使用。11. SYS_INIT 的基本形式系统初始化函数staticintmy_init(void){return0;}SYS_INIT(my_init,POST_KERNEL,50);SYS_INIT()创建一个静态struct init_entry并把它放入.z_init_LEVELPRIORITY_SUBPRIORITY_形式的 linker section。它不代表创建了struct deviceSYS_INIT 只有 system init entrydev 指针为 NULL DEVICE_DT_DEFINE 同时有 device object、device state 和 device init entry12. 本节 boot trace 设计实验注册EARLY:50 PRE_KERNEL_1:80 先写在源码中 PRE_KERNEL_1:20 后写在源码中 PRE_KERNEL_2:50 POST_KERNEL:90 先写在源码中 POST_KERNEL:10 后写在源码中 POST_KERNEL:device:50 APPLICATION:20 main故意逆序书写 priority 80/20 和 90/10是为了排除“按源码出现顺序执行”的错误理解。每个 callback 只调用boot_trace_record(LEVEL:priority);最后由 main 统一打印数组。13. 实际运行结果[init] devicelearning-device-0 initial42 current_before0 *** Booting Zephyr OS build v4.1.0-rc1 *** boot_trace_count9 boot_trace[0]EARLY:50 boot_trace[1]PRE_KERNEL_1:20 boot_trace[2]PRE_KERNEL_1:80 boot_trace[3]PRE_KERNEL_2:50 boot_trace[4]POST_KERNEL:10 boot_trace[5]POST_KERNEL:device:50 boot_trace[6]POST_KERNEL:90 boot_trace[7]APPLICATION:20 boot_trace[8]main [main] devicelearning-device-0 ready1 init_called1 initial42 current42验证结论level 顺序正确 同 level 内数值较小的 priority 先执行 device init 和 SYS_INIT entry 参与同一 POST_KERNEL 排序 APPLICATION 在 main 前执行模拟确认14. linker map 的直接证据查看rg-n-C2\.z_init_(EARLY|PRE_KERNEL_1|PRE_KERNEL_2|POST_KERNEL|APPLICATION)\/mnt/c/study/1-zephyr/work/ch04_init_order/zephyr/zephyr.map实际 section 顺序.z_init_EARLY50_0_ .z_init_PRE_KERNEL_120_0_ .z_init_PRE_KERNEL_180_0_ .z_init_PRE_KERNEL_199_0_ native console .z_init_PRE_KERNEL_20_0_ native timer .z_init_PRE_KERNEL_250_0_ .z_init_POST_KERNEL10_0_ .z_init_POST_KERNEL50_00012_ learning device .z_init_POST_KERNEL90_0_ .z_init_APPLICATION20_0_这说明 linker 不只排列实验代码也把 Zephyr 自带的 console、timer 和 device init 放进同一全局序列。编译确认15. 为什么源码逆序但执行仍有序init.h中#defineZ_INIT_ENTRY_SECTION(level,prio,sub_prio)\__attribute__((__section__(\.z_init_#levelSTRINGIFY(prio)\_STRINGIFY(sub_prio)_)))链接脚本再使用排序SORT_BY_NAME SORT_BY_ALIGNMENT因此真正决定顺序的是section 名 linker script不是C 文件中的函数位置CMake 中源码列出的顺序object 文件碰巧的顺序。16. sub-priority 是什么普通SYS_INIT()本次生成..._0_learning device 生成.z_init_POST_KERNEL50_00012_其中00012对应当前 node 的 dependency ordinal 相关排序信息。它帮助 Zephyr 在相同 level/priority 下处理设备依赖顺序。本节只观察到它存在设备依赖、required handles 和初始化失败传播将在 04-3 展开。不要在应用代码中手工依赖这个生成数字。17. nm 证据nm-n/mnt/c/study/1-zephyr/work/ch04_init_order/zephyr/zephyr.elf\|rgdevice_dts_ord_12|__init_trace实际地址顺序0x10 __init_trace_early_50 0x20 __init_trace_pre1_20 0x30 __init_trace_pre1_80 0x60 __init_trace_pre2_50 0x70 __init_trace_post_10 0x80 __init___device_dts_ord_12 0x90 __init_trace_post_90 0xa0 __init_trace_application_20与运行时记录一致。编译确认18. device init 可以选哪些 levelDEVICE_DEFINE()/DEVICE_DT_DEFINE()文档面向普通 device 时列出PRE_KERNEL_1 PRE_KERNEL_2 POST_KERNEL选择原则必须在 kernel 前准备的底层设备 - PRE_KERNEL level但必须遵守严格限制 需要 kernel primitives 或常规设备依赖 - POST_KERNEL 纯应用初始化 - 通常使用 SYS_INIT(..., APPLICATION, ...)不要为了“更早”而盲目选择 PRE_KERNEL。过早会让可用 API 更少、依赖关系更难满足。19. 初始化 priority 不是延时priority 10 priority 90不表示相差 80 ms每个 init 有固定时间片priority 10 一定执行得更快调度器 thread priority。它只表示同一 level 中 init entry 的相对排序键。如果 priority 10 的 init 阻塞很久priority 90 仍必须等待它返回。21. 常见错误21.1 认为所有 priority 在全局比较priority 只在相同 level 内比较。21.2 把 init priority 与 thread priority 混淆init priority 是链接排序thread priority 是 scheduler 概念。21.3 PRE_KERNEL 中使用 kernel primitive此时 kernel services 尚不可用。21.4 EARLY 阶段打印大量日志console/logging backend 可能尚未初始化。应使用最小、无依赖的状态记录。21.5 使用 priority 算术表达式section 名生成要求 literal 或可直接展开的 symbolic integer。21.6 用源码书写顺序推断执行顺序应检查 level、priority、生成 section 和最终 map。21.7 随意调整 driver priority 修复依赖如果 Devicetree 已表达设备依赖应优先理解依赖图和自动排序而不是靠不断试 priority 数字。下一节会专门学习。22. 可迁移到其他驱动的结论SYS_INIT 和 device init 使用同一 init entry/linker section 基础设施初始化先按 level、再按 priority、最后按 sub-priority 排序同 level 中数值较小的 priority 先执行PRE_KERNEL 阶段不能假设 kernel services 可用POST_KERNEL 是普通 device driver 的常见选择APPLICATION init 发生在 main 之前最终zephyr.map是确认真实 init 顺序的重要证据。23. 练习与自测请执行rg-n-C2\.z_init_(EARLY|PRE_KERNEL_1|PRE_KERNEL_2|POST_KERNEL|APPLICATION)\/mnt/c/study/1-zephyr/work/ch04_init_order/zephyr/zephyr.map然后回答PRE_KERNEL_2:99与POST_KERNEL:0哪个先执行为什么同为POST_KERNEL时priority 10、50、90 的顺序是什么为什么实验在 EARLY 阶段只记录内存而不直接打印为什么源码中 priority 80 写在 20 前面最终仍是 20 先执行SYS_INIT()与DEVICE_DT_DEFINE()的 init entry 有什么共同点和区别下一节04-3-初始化失败、设备依赖与device_is_ready。

相关新闻

第三篇:《在 Kubernetes 中部署 Istio:安装、配置与 Sidecar 注入》

第三篇:《在 Kubernetes 中部署 Istio:安装、配置与 Sidecar 注入》

理解了 Istio 的架构之后,是时候亲手搭建一个 Istio 环境了。在 Kubernetes 集群中安装 Istio 有多种方式,最常用的是 istioctl 命令行工具和 Helm。本文将详细介绍使用 istioctl 安装 Istio 的完整流程,涵盖环境准备、安装配置文件的选型、命…

2026/10/10 15:57:25 阅读更多 →
AI音乐生成实战:Spark项目本地部署与结构化音乐生成解析

AI音乐生成实战:Spark项目本地部署与结构化音乐生成解析

如果你是一位音乐爱好者、内容创作者,或者正在寻找一种高效、低成本的方式为自己的视频或项目制作高质量背景音乐,那么你很可能已经对“AI音乐生成”这个领域产生了兴趣。但面对市面上众多的AI音乐工具,一个核心的痛点始终存在:生…

2026/10/13 2:18:17 阅读更多 →
黄金价格软件国内外价格实时监控超方便

黄金价格软件国内外价格实时监控超方便

软件介绍 GOLDALL,一款黄金价格实时监控工具。最近黄金价格跌得厉害,今天的价格好像已经到866一克了,真的是跌跌不休。如果你也在关注黄金行情,这款软件值得了解一下。 国内外价格实时显示 软件可以同时显示黄金的国内价格和国…

2026/10/13 7:23:21 阅读更多 →

最新新闻

Java基础探秘:JSON解析与反射机制如何协同工作

Java基础探秘:JSON解析与反射机制如何协同工作

最近在写一个接口的时候,我盯着IDE里那几十行setter调用,脑子里突然冒出一个问题:前端传过来一段JSON字符串,我一行代码就把它变成了业务对象,中间到底是谁在帮我完成键名和字段的匹配?顺着这个疑问查下去&…

2026/10/14 6:41:29 阅读更多 →
QGIS 加载天地图出现灰色影像:层级参数 l 与 z 的坑,附四种返回码对照

QGIS 加载天地图出现灰色影像:层级参数 l 与 z 的坑,附四种返回码对照

场景QGIS 里挂天地图底图,图层加成功了,瓦片也在刷,画面却是一片灰,每个格子上写着"此级别下,该区域无影像"。打开浏览器 F12 一看,状态码 200,图片也确实回来了。这时候大多数人会往…

2026/10/14 6:41:29 阅读更多 →
Agent通信协议选型指南:JSON-RPC、MCP、A2A与ACP的分层实践

Agent通信协议选型指南:JSON-RPC、MCP、A2A与ACP的分层实践

1. 为什么 Agent 通信协议突然“百花齐放”过去一年里,只要你在做 AI Agent 相关的开发,几乎绕不开一个困惑:同样是让两个智能体互相说话,怎么一会儿是 JSON-RPC,一会儿是 MCP,转头又冒出 A2A、ACP&#xf…

2026/10/14 6:41:29 阅读更多 →
Chat2DB 实战:AI 生成 SQL 的数据库管理工具与避坑指南

Chat2DB 实战:AI 生成 SQL 的数据库管理工具与避坑指南

简介:Chat2DB项目代码包是一份集成人工智能能力的开源数据库管理工具示例,面向需要降低数据库操作门槛的开发者、数据分析师以及对自然语言生成SQL感兴趣的技术人员。整个资源共包含3个文件,涵盖inscode入口文件、html介绍文档以及gitignore配…

2026/10/14 6:41:29 阅读更多 →
PS5串流实战:AnyPS5配置与网络调优全攻略

PS5串流实战:AnyPS5配置与网络调优全攻略

把一台PS5玩出三台机器的效果,是不少玩家都在琢磨的事。AnyPS5这个项目,说白了就是干这件事:让PS5不再被客厅电视绑住,而是把画面和操作实时串流到你手边的任何一块屏幕上——笔记本、平板、手机、甚至办公电脑。我在这个方向上前…

2026/10/14 6:41:29 阅读更多 →
C#调用WebService获取PDF转图片:选型与踩坑实战

C#调用WebService获取PDF转图片:选型与踩坑实战

做C#开发这几年,遇到“调用WebService获取PDF文件再转换为图片”这种需求不算少。可能是一个审批系统需要预览合同,也可能是一个报表平台需要把服务端生成的文件转成缩略图展示。总之核心工作就两件事:把远程文件拿下来,再在本地转…

2026/10/14 6:40:29 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →