开发者社区> 开发者小助手> 正文

AliOS Things内核延迟加载技术

简介: 在某些应用场景中,要求系统能快速启动。从用户视角看,只有当系统的应用逻辑开始运行的时候,才算启动完成。所以,启动时间并不只是从系统上电到操作系统完成初始化,还包从初始化完成到基本功能开始运行的时间。比如IP Camera要求从上电到第一帧稳定出图的时间小于250ms,这个启动时间包含了第一帧图像的采集与显示。
+关注继续查看

一、概述

在某些应用场景中,要求系统能快速启动。从用户视角看,只有当系统的应用逻辑开始运行的时候,才算启动完成。所以,启动时间并不只是从系统上电到操作系统完成初始化,还包从初始化完成到基本功能开始运行的时间。比如IP Camera要求从上电到第一帧稳定出图的时间小于250ms,这个启动时间包含了第一帧图像的采集与显示。

本文阐述了AliOS Things上的内核延迟加载技术,可有效降低系统启动时间。

二、操作系统可执行程序的组成

操作系统的可执行程序主要包含text、rodata、data、bss段。其中text存放代码;rodata段存放只读数据,比如字符串;data段存放初始化为非0的全局变量;bss段存放未初始化和初始化为0的全局变量。

编译生成的可执行程序bss段上并没有实质性内容,只需在OS初始化时将其对应的内存区域全部清0即可,因此生成的系统镜像只包含text、rodata、data段。

编译生成系统镜像后,用烧录器将镜像烧写到Flash上。当系统上电或RESET时,首先运行BootLoader,它从FLASH读取系统镜像,并将其写到指定的RAM区域,然后跳转到系统入口。

为了尽早暴露问题,提高系统的稳定性,操作系统通常根据段的特点设置其所在内存的属性。text段设置为只读可执行,这样往该区域写数据将直接触发异常,避免指令被误修改引发不可预知的问题。rodata段也类似,操作系统只会从该段读取数据不会往该段写数据,因此设置为只读属性。

三、延迟加载

读取Flash较为耗时,以读速度20MB/s的flash为例,BootLoader读取2MB内核镜像需要约100ms。对于需在250ms内出图的IP Camera应用来说,这个时间已经耗去40%,必须降低该时间。

从操作系统初始化到启动完成并不需要所有的代码段与数据段。因此可以把内核的加载操作分为两个阶段,第一阶段由BootLoader加载,包括操作系统启动需要的代码和数据。第二阶段在操作系统完成启动后,由操作系统自己把镜像剩余部分加载到内存。各个阶段的如下:

具体而言,延迟加载技术通过链接脚本将OS镜像分为启动加载和延迟加载两部分。从原始的text、rodata、data段中分离出延迟加载的post_text、post_rodata、post_data段。其中text、rodata、data段由BootLoader加载,post_text、post_rodata、post_data段由操作系统加载。具体划分如下图所示:

链接脚本有两种方式来支持上述内核镜像布局。

3.1、正向选择

链接脚本语法如下:
archive:file (.segment)
其中,archive是库名,通常是.a为后缀的库。file是库内文件,通常为.o后缀的目标文件,file也可以省略,表示链接archive内的所有文件。archive:file也可以用通配符*,表示链接所有的文件。通过该语句可以指定只链接某个库的段或链接所有库的段。因此可在链接脚本中先链接启动加载部分的代码与数据,然后再链接剩余部分。示例如下:

/* 链接启动加载部分 */

  1. __text_start = .;
  2. .text :
  3. {
  4. kernel.a:(.text .text*)
  5. }
  6. .rodata :
  7. {
  8. kernel.a:(.rodata .rodata*)
  9. }
  10. .data :
  11. {
  12. kernel.a:(.data .data*)
  13. }

/* 链接剩余部分 */

  1. .post_text :
  2. {
  3. __post_text_start = .;
  4. *(.text .text*)
  5. __post_text_end = .;
  6. }
  7. .post_rodata :
  8. {
  9. __post_rodata_start = .;
  10. *(.rodata .rodata*)
  11. __post_rodata_end = .;
  12. }
  13. .post_data ALIGN(0x1000):
  14. {
  15. __post_data_start = .;
  16. *(.data .data*)
  17. __post_data_end = .;
  18. }
  19. .bss :
  20. {
  21. *(.bss .bss*)
  22. }

3.2、反向选择

如果启动加载部分的库比较多,且很难清理出一个完整的列表。那么可以利用链接脚本提供的EXCLUDE_FILE关键字反向选择。即把可以放到延迟加载部分的库梳理出来,然后从第一部分剔除。EXCLUDE_FILE语法如下:
EXCLUDE_FILE (archive0 archive1 archive2) *(.segment)
EXCLUDE_FILE语句一次可以指定排除多个库。示例如下:

/* 链接启动加载部分 */

  1. __text_start = .;
  2. .text :
  3. {
  4. EXCLUDE_FILE(post.a) *(.text .text*)
  5. }
  6. .rodata :
  7. {
  8. EXCLUDE_FILE(post.a) * (.rodata .rodata*)
  9. }
  10. .data :
  11. {
  12. EXCLUDE_FILE(post.a) * (.data .data*)
  13. }

/* 链接剩余部分 */

  1. .post_text :
  2. {
  3. __post_text_start = .;
  4. *(.text .text*)
  5. __post_text_end = .;
  6. }
  7. .post_rodata :
  8. {
  9. __post_rodata_start = .;
  10. *(.rodata .rodata*)
  11. __post_rodata_end = .;
  12. }
  13. .post_data ALIGN(0x1000):
  14. {
  15. __post_data_start = .;
  16. *(.data .data*)
  17. __post_data_end = .;
  18. }
  19. .bss :
  20. {
  21. *(.bss .bss*)
  22. }

链接脚本中定义了符号text_start,同时为延迟加载的段定义了三组符号:post_text_start/post_text_endpost_rodata_start/post_rodata_endpost_data_start/post_data_end。系统启动后可以根据这些符号确定加载到内存的位置,以及设置相应的读写属性。可以根据post_text_start-__text_start的偏移值计算出指定延迟加载段在flash中的偏移。

在实际项目中,通过上述反向选择方式,BootLoader只需加载原镜像的60%,BootLoader耗时从114ms降为72ms。

在代码和数据被加载前,存放延迟加载段的内存上的值是随机值,因此该内存区域的属性宜在加载前设置,以避免误访问该区域产生不可预知的问题。操作系统从Flash加载延迟部分的流程如下。它将根据是否使能延迟加载功能来决定是否从flash读取延迟加载的段。

最后,还有一个问题需要解决:BootLoader如何获得第一部分的加载长度。第一种方式是静态配置,即配置BootLoader源码的加载长度宏。这种方式实现简单,适合在内核镜像变化不大的情况下使用。第二种方式是构建体系自动探测。编译生成内核镜像后,构建体系读取链接时生成的map文件,然后获取第一部分加载长度,并设置BootLoader的编译宏。第三种方式是在内核镜像头部存放第一部分加载长度的信息,BootLoader先读取内核镜像头部,获得第一部分的加载长度后,再继续加载。

四、总结

本文阐述了AliOS Things上的内核延迟加载技术。提供了两种调整内核镜像的方式,可有效降低启动时间。

开发者技术支持

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Win10 UWP xaml 延迟加载元素
原文:Win10 UWP xaml 延迟加载元素 xaml新增x:DeferLoadStrategy里面只有Lazy,查询了百度看到MSP_甄心cherish大神说的 xaml使用x:DeferLoadStrategy="Lazy"延迟加载元素 我写了代码 ...
613 0
延迟加载算法微服务的模型
基于SpringBoot的算法微服务,通常在启动阶段加载算法模型。但因为业务上,模型大小和数量是动态的,因此这一过程短则1分钟,长则5+分钟。在启动时加载导致的启动时间过长,会影响服务自身的监控告警、健康检测。
8294 0
RDLC报表 在WinForm里运行出现 未能加载文件或程序集 Microsoft.ReportViewer.WinForms, Version=11.0.0.0 System.IO.FileNotFoundException
原文:RDLC报表 在WinForm里运行出现 未能加载文件或程序集microsoft.reportviewer.winforms 推荐以下方案二 做一下记录顺便帮助一下遇到问题的朋友。 做RDLC报表在WinForm运行,在VS里面调试引用了“Microsoft.ReportViewer.Common.dll”和“Microsoft.ReportViewer.WinForms.dll”调试运行的时候没有问题。
1325 0
Mybatis查询延迟加载
Mybatis查询延迟加载   目录 1.1        启用延迟加载 1.2        分析 1.3        aggressiveLazyLoading 1.4        lazyLoadTriggerMethods   1.1     启用延迟加载        Mybatis的延迟加载是针对嵌套查询而言的,是指在进行查询的时候先只查询最外层的SQL,对于内层SQL将在需要使用的时候才查询出来。
752 0
IDA反汇编/反编译静态分析iOS模拟器程序(二)加载文件与保存数据库
启动windows版的IDA,在Quickstart界面点击New,弹出一个对话框选择文件。也可以按取消后再把文件拖进IDA。由于Mac版的IDA没注册,没有save功能,所以只好先把Mac上的东西拷贝到windows再打开了。
1114 0
未能加载文件或程序集 Microsoft.ReportViewer.Common, Version=11.0.0.0
原文: 未能加载文件或程序集 Microsoft.ReportViewer.Common, Version=11.0.0.0 System.IO.FileNotFoundException: 未能加载文件或程序集“Microsoft.ReportViewer.Common, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91”或它的某一个依赖项。
1332 0
I.MX6 android shutdown 内核崩溃
/**************************************************************************** * I.MX6 android shutdown 内核崩溃 * 说明: * 本文主要是记录解决I.MX6的关机会进入halt模式,导致内核崩溃。
738 0
1482
文章
343
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载