资讯专栏INFORMATION COLUMN

震惊!这个操作系统的应用加载只需要“毫秒级”耗时

incredible / 2519人阅读

摘要:本文主要介绍应用程序加载如何做到毫秒级耗时。图不同视角看左边是从汇编器和链接器的视角来看这个文件,开头的描述了体系结构和操作系统等基本信息,并指出和在文件中的什么位置,在汇编和链接过程中没有用到,所以是可有可的,中保存了所有的描述信息。

1、背景

AliOS ThingAliOS家族旗下面向IoT领域的、高可伸缩的物联网操作系统,AliOS Thing v3.2[1]以后的版本提供了内核和应用程序分离的功能,内核和应用分别运行在不同的虚拟地址空间,即使应用程序出现问题也不会影响到内核的运行。内核和应用程序的隔离,不仅可以达到安全的目的,还可以有效降低应用开发的成本,并且应用程序以标准的ELF (Executable and Linkable Format)[2]文件存在,系统需要运行哪一个应用程序,只需要加载该应用程序的ELF文件即可。

本文主要介绍AliOS Things应用程序加载如何做到“毫秒级”耗时。

图1-1 AliOS Things

2、ELF 文件格式

    ELF文件格式提供了两种不同的视角,在汇编器和链接器看来,ELF文件是由Section Header Table描述的一系列Section的集合,而执行一个ELF文件时,在加载器Loader看来它是由Program Header Table描述的一系列Segment的集合。

图2-1 不同视角看ELF

    左边是从汇编器和链接器的视角来看这个文件,开头的ELF Header描述了体系结构和操作系统等基本信息,并指出Section Header TableProgram Header Table在文件中的什么位置,Program Header Table在汇编和链接过程中没有用到,所以是可有可的,Section Header Table中保存了所有Section的描述信息。右边是从加载器的视角来看这个文件,开头是ELF HeaderProgram Header Table中保存了所有Segment的描述信息,Section Header Table在加载过程中没有用到,所以是可有可无的。注意Section Header TableProgram Header Table并不是一定要位于文件开头和结尾的,其位置由ELF Header指出,上图这么画只是为了清晰。

    我们在汇编程序中用.section声明的Section会成为目标文件中的Section,此外汇编器还会自动添加一些Section(比如符号表),Segment是指在程序运行时加载到内存的具有相同属性的区域,由一个或多个Section组成,比如有两个Section都要求加载到内存后可读可写,就属于同一个Segment。有些Section只对汇编器和链接器有意义,在运行时用不到,也不需要加载到内存,那么就不属于任何Segment。目标文件需要链接器做进一步处理,所以一定有Section Header Table;可执行文件需要加载运行,所以一定有Program Header Table;而共享库既要加载运行,又要在加载时做动态链接,所以既有Section Header Table又有Program Header Table

3、AliOS Things应用程序ELF格式

图3-1 AliOS Things ELF

    目前的AliOS Things应用程序ELF文件暂不支持类似于.so文件的动态加载和地址重定位,ELF文件一旦编译生成之后,该ELF加载之后运行的虚拟地址就固定(由链接脚本确定)下来了,如图3-1中的Program Header中的LOAD对应的虚拟地址起始地址是0x10000000,相较于整个ELF文件的偏移量是0x010000

4、ELF文件加载方式思考

以前的传统加载方式,分成个步骤,如图4-1所示:

  1. 打开ELF文件,并把整个ELF读取到内存,然后解析ELF的格式,找到需要加载的LOAD Program Header;
  2. 一次申请所有的内存,并完成该ELF虚拟地址空间映射到对应的物理内存,需要的内存大小为app_text_end - app_text_start;
  3. ELF文件中.text,ARM.exidx,.ctors,.rodata,.ARM.extab,.ARM.extab.text.u,.data,.got,.FSymTab部分搬运到 虚拟地址范围app_text_start ~ app_text_end对应的存储区,同时把虚拟地址范围app_zero_start ~ app_zero_end对应的存储区全部清零。
  4. 创建进程执行该ELF的代码;

图4-1 传统加载方式示意

通过上述步骤可以发现如下2个问题:

  1. 无论是否需要把整个ELF文件都全部加载,加载器都首先把全部文件都读取到内存,导致加载的耗时较长;真实的情况可能只需要加载ELF文件的一部分内容应用程序就可以运行了;
  2. 无论整个虚拟地址空间(app_text_start ~ app_zero_end)是否都需要映射到物理内存,整个虚拟都一次全部映射,导致不必要的内存浪费;地址空间,到内存打开ELF文件,并把整个ELF读取到内存,然后解析ELF的格式,找到需要加载的LOAD Program Header;

上述2个方面也是我们新的加载器(分段快速加载引擎)重点优化的两个方面;

5、分段快速加载引擎

图5-1 AliOS Things分段加载引擎

  • ELF预先读取程序入口,后续按需缺页中断加载;
  • 虚拟地址空间预先映射一部分,后续按需缺页中断映射,预先映射的部分可以根据缺页中断统计信息调整,提高加载的速度;

图5-2 AliOS Things示意图

    基于IP Camera客户的应用程序测试发现,整个虚拟地址空间只需要映射1/4部分程序就可以正常运行,整个ELF文件只需要读取ELF HeaderProgram Header Table获取LOAD segment字段描述信息,根据这些信息设置好缺页中断即可运行,应用程序完全运行起来,只需要加载和映射大概1/4内容,借助于分段快速加载引擎(bengine_dload)加载2M Bytes大小的ELF文件的速度可以从500 ms优化到80 ms左右部分,内存开销从3.5 MB (2MB code + 1.5MB BSS)降低到1.25 MB (256KB code + 1MB bss)分段快速加载引擎可以对应用程序的加载速度提高6倍以上,内存开销降低2.8

 

开发者支持

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

更多技术与解决方案介绍,请访问HaaS官方网站https://haas.iot.aliyun.com

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121966.html

相关文章

  • 1.5s~0.02s,期间我们可以做些什么?

    摘要:而且需要在特定的菜单位置上显示待办事项的数量。以我的博客某篇文章加载为例最右边有个红框标识的就是每条资源的加载耗时,我们可以看到第一条是服务端的处理速度。接下来我们就可以直接去看代码了。在大脑中构思了一下,其实这些完全可以通过递归来实现嘛。 原文是在我自己博客中,小伙伴也可以点阅读原文进行跳转查看,还有好听的背景音乐噢背景音乐已取消~ 2333333 大爷我就算功能重做,模块重构,我...

    novo 评论0 收藏0
  • 定时器在大型web项目中应用和实现

    摘要:在软件项目中,定时器也被应用到了各方各面,本文将从项目入手,讲述定时器,本文的例子都以为例。定时器总类定时器有两种对应重复任务和一次性任务。 在大规模分布式系统中,每个业务都可能是集群,每个业务机都会产生定时任务,不同的业务会有不同的任务管理需求,统一的任务调度和管理变得非常有必要。 定时如何准确,大量的定时被同时触发怎么办? 定时结束的时候,怎么通知业务机去处理呢? 某台业务机下线...

    douzifly 评论0 收藏0
  • 定时器在大型web项目中应用和实现

    摘要:在软件项目中,定时器也被应用到了各方各面,本文将从项目入手,讲述定时器,本文的例子都以为例。定时器总类定时器有两种对应重复任务和一次性任务。 在大规模分布式系统中,每个业务都可能是集群,每个业务机都会产生定时任务,不同的业务会有不同的任务管理需求,统一的任务调度和管理变得非常有必要。 定时如何准确,大量的定时被同时触发怎么办? 定时结束的时候,怎么通知业务机去处理呢? 某台业务机下线...

    whataa 评论0 收藏0
  • 记一次tornado QPS 优化

    摘要:初步分析提升可从两方面入手,一个是增加并发数,其二是减少平均响应时间。大部分的时间花在系统与数据库的交互上,到这,便有了一个优化的主题思路最大限度的降低平均响应时间。不要轻易否定一项公认的技术真理,要拿数据说话。 本文最早发表于个人博客:PylixmWiki 应项目的需求,我们使用tornado开发了一个api系统,系统开发完后,在8核16G的虚机上经过压测qps只有200+。与我们当...

    Doyle 评论0 收藏0

发表评论

0条评论

incredible

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<