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/9/23 22:43:18 阅读更多 →
AI音乐生成实战:Spark项目本地部署与结构化音乐生成解析

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

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

2026/9/18 7:29:35 阅读更多 →
黄金价格软件国内外价格实时监控超方便

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

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

2026/9/21 20:30:33 阅读更多 →

最新新闻

PRQL 的 Elixir 绑定:使用 Rustler NIF 在 Elixir 中编译 PRQL 查询

PRQL 的 Elixir 绑定:使用 Rustler NIF 在 Elixir 中编译 PRQL 查询

后端 【免费下载链接】prql PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement 项目地址: https://gitcode.com/gh_mirrors/pr/prql 点击查看 免费下载 本指南围绕 PRQL 仓库中的 Elixir 语言绑定(位…

2026/9/23 23:22:44 阅读更多 →
Captura 命令行安装 FFmpeg 全解析:`captura-cli ffmpeg --install` 的使用与底层原理

Captura 命令行安装 FFmpeg 全解析:`captura-cli ffmpeg --install` 的使用与底层原理

桌面应用屏幕录制音视频 【免费下载链接】Captura Capture Screen, Audio, Cursor, Mouse Clicks and Keystrokes 项目地址: https://gitcode.com/gh_mirrors/ca/Captura 点击查看 免费下载 本篇技术指南聚焦 Captura 开源截屏/录屏项目(当前仓库 gh_mi…

2026/9/23 23:22:44 阅读更多 →
疫情舆情情感分析实战:从pandas解析到朴素贝叶斯建模

疫情舆情情感分析实战:从pandas解析到朴素贝叶斯建模

简介:这是一份面向自然语言处理与舆情分析方向学习者、研究者的疫情情感分析完整项目,围绕2020年疫情期间人民日报与微博等平台话题数据,实现情感极性的两分类分析。资源整合了毕业论文文档、Python项目源码与多格式实验数据,共20…

2026/9/23 23:22:44 阅读更多 →
Python大熊猫互动拍照系统:姿态估计与图像融合技术实战解析

Python大熊猫互动拍照系统:姿态估计与图像融合技术实战解析

简介:这是一套面向毕业设计及AI图像处理学习的Python大熊猫主题互动拍照系统源码。项目围绕人工智能视觉技术,实现了动作识别、人像动漫化、风格迁移、熊猫贴纸合成、视频融合及定时拍照等完整功能,适合需要完成课程设计、毕业设计或希望实战…

2026/9/23 23:22:44 阅读更多 →
在 Laradock 上使用 Docker 运行 Kanboard:从本地到生产的完整指南

在 Laradock 上使用 Docker 运行 Kanboard:从本地到生产的完整指南

在 Laradock 上使用 Docker 运行 Kanboard:从本地到生产的完整指南 【免费下载链接】laradock Full PHP development environment for Docker. Run Laravel, Symfony, CodeIgniter, Phalcon, WordPress, Drupal, Magento, Moodle, or any PHP project with 70 pre-c…

2026/9/23 23:22:44 阅读更多 →
鸟类识别目标检测数据集构建与YOLOv8训练避坑指南

鸟类识别目标检测数据集构建与YOLOv8训练避坑指南

简介:一份面向目标检测与深度学习实战的鸟类识别数据集,适用于YOLO系列、Faster RCNN、SSD等模型训练,覆盖10个常见鸟类类别,共16287张图片。资源已按训练集、验证集和测试集划分,并配套VOC格式XML标签、YOLO格式txt标…

2026/9/23 23:21:43 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →