当前位置: 首页 > news >正文

LAYER_INITCALL宏

要理解LAYER_INITCALL宏,需要从宏定义拆解,编译器特性,链接脚本配合,实际作用场景四个维度来剖析——它是arkui-LITE 实现分层初始化的核心 技术,本质 是通过 编译器段属性+链接脚本排序。让初始化函数按预调优先级自动 执行,无需手动调用

一:分析每个参数与关键字的作用
先将宏定义 拆分成参数 ,修饰符,赋值三个部分,明确每个部分的功能
#define LAYER_INITCALL(func, layer, clayer, priority) \
//1. 定义静态常量变量,类型为iinitcall, 变量名包含 func layer 避免重复
static const InitCall USED_ATTR _zinitcall##layer##_##func
//2. 编译器的特性,将变量放入指定 段(zinitcall.xxx.xxx.init)
attribute((section(“.zinitcall.” clayer #priority “.init”))) = func //将变量强制放入指定的自定义段,而非默认的.data/.bss段。
#endif
1:宏参数解析
func 要注册的初始化函数,如硬件驱动初始化,系统服务启动函数 spidriverInit SPI驱动初始化
layer 逻辑分层标识(仅用于变量名,避免不同层函数重名) device 设备驱动层
clayer 段分层标识(链接脚本中定义 的分层 ,如device core sys_service) device (对应链接脚本的设备层段)
priority 同一分层内的执行优先级,数值越小,初始化越早 100 设备层默认优先级

当clayer = “device” priority =100时,段名为.zintcall.device.10.init——后续链接脚本会通过这个段名找到所有设备层的初始化函数

3:变量类型与赋值:
initcall是一个函数指针类型,用于存储初始化函数的地址 ,定义如下
typedef void (*InitCall)(void)
宏的最后=func 表示,将初始化函数func的地址 ,赋值给_zinitcall_##layer##_##func 这个函数指针变量,最终效果是把func的地址 存到了section指定的段中。

三:宏的依赖,链接脚本如何配合
LAYER_INITCALL宏本身 只负责把函数地址放入指定的段,但是让这些函数按顺序执行,必须 依赖链接脚本.ld文件配合,链接脚本负责 定义段的地址范围和排序段内的变量
链接脚本的3个关键作用
KEEP(…) :和宏中的USED_ATTR配合,强制链接器保留这些段,即使看起来没有调用 ,避免初始化函数被误删。
SORT(…):对同层内的段按优先级数值 排序,例如,设备导.zinitcall.device.99.init会排在.zinitcall.device.100.init前面 ,确保优先级99的函数先执行
__zinitcall_xxx_start/end:标记每个层的段起始,结束 地址 ,后续初始化代码可以通过这些地址 遍历该层所有 初始化函数。

四:宏的最终价值,如何被调用执行。
通过LAYER_INITCALL注册的函数,最终由Openharmony的初始化管理器,如bootstarp_lite调用 ,核心 逻辑是按层遍历段地址,逐个执行函数指针。

调用 的时机,系统启动的分层阶段:
在OHOS_SystemInit(系统初始化入口 中),会按BSP层,设备层,服务层 应用层,的顺序调用 MODULE_CALL例如:

在这里插入图片描述

五:宏的设计目的,为什么 需要它
在嵌入式系统中,初始化函数往往有严格 的依赖顺序 。如:必须先初始化时钟,才能初始化spi,必须先初始化spi ,才能初始化 spi flash, LAYER_INITCALL宏的核心 价值就是解决,初始化顺序管理问题,相比传统手动调用 有3个优势 。
1:解耦:无需手动维护调用 顺序
传统方式 需要在main 函数中手动写 clockInit->spiinit()->spiFlashInit().一旦新增驱动,就要 修改main
用LAYER_INITCALL后,只需要维新的驱动函数指定正确 的clayer 和priority,链接脚本和MODULE_CALL 会自动的按顺序执行,无需要修改原有 代码
2.灵活:支持模块化裁剪。
嵌入式设备的资源有限,如64KB RAM ,常需要裁剪功能,如不需要网络,就删除网络驱动
用LAYER_INITCALL注册的函数,若模块被裁剪,如spi_driver.c没有加入 编译,对应的段会自动消失 ,不会影响其它初始化流程,传统手动调用 会导致 编译错误(未定义函数)

总结:LAYER_INITCALL 宏的本质
编译器段特性+链接脚本排序+遍历 调用 组合,用公式可以概括为:
初始化函数+LAYER_INITCALL参数-》函数地址存入指定的段-》链接脚本排序段-》MODULE_CALL遍历段执行函数
它是ArkUI-Lite实现分层初始化的基石,确保了轻量级嵌入式设备中,从硬件驱动到上层UI框架的初始化流程有序,可控,可裁剪。

http://www.dtcms.com/a/420662.html

相关文章:

  • M| 怪形
  • 在Linux中快速下载Conda的方法
  • 如何做自己的简历网站wordpress文库主题
  • 数据库-锁
  • 解决 Python Crypto安装后依然无效的问题
  • 数字化转型:概念性名词浅谈(第五十六讲)
  • solidworks 实体分割 保存实体 后转换钣金 钣门框出图 结构构件添加 钣金出图教程 平板样式不是展开解决办法 比例激活1比1
  • (Kotlin协程六)协程和RxJava的区别
  • 企业网站制作及cms技术网站开发文档教学
  • 比较好的建立站点如何修改wordpress主题
  • 想让客户公司做网站的话语wordpress s5主题
  • 网站制作框架公司网页怎么制作教程
  • 【实战】理解服务器流量监控中的“上行”和“下行”
  • 洛阳直播网站建设个人空间网站
  • MyBatis-Plus使⽤
  • 长春网站制作报价南京软件定制
  • 烟台网站建设方案wordpress推荐好友
  • 著名网站用什么语言做后台定制软件开发报价
  • 质量好网站建设商家建设网站的建设费用包括哪些内容
  • 《Linux 基础 IO 完全指南:从文件描述符到缓冲区》
  • 如何上传ftp网站程序c 做网站开发
  • 【Linux】库的制作与原理(1)
  • 网站建设策划书悠悠如何做百度竞价推广
  • NVIDIA Warp v1.9.0深度解析:GPU加速物理仿真与计算的革命性进展
  • 网站怎么挂广告有没有做字的网站
  • dede电影网站模版个人博客模板wordpress
  • 临清设计网站网站建立价格
  • 公司电子商务网站建设规划方案米拓网站建设步骤
  • 易基因:Cell Res/IF25.9:童明汉/蓝斐/汤富酬合作利用ChIP-seq及多组学分析揭示精子发生的表观遗传调控机制
  • 免费免费网站模板wordpress主题更换字体教程 | hu