未验证 提交 7f704c8f 编写于 作者: O openharmony_ci 提交者: Gitee

!3056 格式调整适配官网发布。--不涉及翻译

Merge pull request !3056 from Austin/OpenHarmony-3.1-Release
...@@ -41,7 +41,7 @@ In addition, OpenHarmony provides a series of optional system components that ca ...@@ -41,7 +41,7 @@ In addition, OpenHarmony provides a series of optional system components that ca
| Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices&nbsp;based<br/>&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[WLAN-connected&nbsp;Products](guide/device-wlan-led-control.md)<br/>-&nbsp;[Cameras&nbsp;Without&nbsp;a&nbsp;Screen](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[Cameras&nbsp;with&nbsp;a&nbsp;Screen](guide/device-camera-control-overview.md) | | Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices&nbsp;based<br/>&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[WLAN-connected&nbsp;Products](guide/device-wlan-led-control.md)<br/>-&nbsp;[Cameras&nbsp;Without&nbsp;a&nbsp;Screen](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[Cameras&nbsp;with&nbsp;a&nbsp;Screen](guide/device-camera-control-overview.md) |
| Porting&nbsp;and&nbsp;adaptation | -&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the&nbsp;<br/>OpenHarmony&nbsp;to&nbsp;an&nbsp;SoC<br/>-&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a<br/>&nbsp;third-party&nbsp;library | -&nbsp;[Mini&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[Small&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[Third-Party&nbsp;Library&nbsp;Porting&nbsp;Guide&nbsp;for&nbsp;Mini&nbsp;and&nbsp;Small&nbsp;Systems](porting/porting-thirdparty-overview.md) | | Porting&nbsp;and&nbsp;adaptation | -&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the&nbsp;<br/>OpenHarmony&nbsp;to&nbsp;an&nbsp;SoC<br/>-&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a<br/>&nbsp;third-party&nbsp;library | -&nbsp;[Mini&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[Small&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[Third-Party&nbsp;Library&nbsp;Porting&nbsp;Guide&nbsp;for&nbsp;Mini&nbsp;and&nbsp;Small&nbsp;Systems](porting/porting-thirdparty-overview.md) |
| Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) | | Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) |
| Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | -&nbsp;[API&nbsp;References](https://gitee.com/link?target=https%3A%2F%2Fdevice.harmonyos.com%2Fen%2Fdocs%2Fapiref%2Fjs-framework-file-0000000000616658)<br/>-&nbsp;[FAQs](faqs/faqs-overview.md) | | Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md) |
**Table 2** Standard system development guidelines \(reference memory ≥ 128 MB\) **Table 2** Standard system development guidelines \(reference memory ≥ 128 MB\)
...@@ -55,5 +55,5 @@ In addition, OpenHarmony provides a series of optional system components that ca ...@@ -55,5 +55,5 @@ In addition, OpenHarmony provides a series of optional system components that ca
| Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices<br/>&nbsp;based&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[Development&nbsp;Guidelines&nbsp;on&nbsp;Clock&nbsp;Apps](guide/device-clock-guide.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Platform&nbsp;Drivers](guide/device-driver-demo.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Peripheral&nbsp;Drivers](guide/device-outerdriver-demo.md) | | Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices<br/>&nbsp;based&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[Development&nbsp;Guidelines&nbsp;on&nbsp;Clock&nbsp;Apps](guide/device-clock-guide.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Platform&nbsp;Drivers](guide/device-driver-demo.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Peripheral&nbsp;Drivers](guide/device-outerdriver-demo.md) |
| Porting&nbsp;and&nbsp;adaptation | Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a&nbsp;third-party&nbsp;library | -&nbsp;[Standard&nbsp;System&nbsp;Porting&nbsp;Guide](porting/standard-system-porting-guide.md)<br/>-&nbsp;[A&nbsp;Method&nbsp;for&nbsp;Rapidly&nbsp;Porting&nbsp;the&nbsp;OpenHarmony&nbsp;Linux&nbsp;Kernel](porting/porting-linux-kernel.md) | | Porting&nbsp;and&nbsp;adaptation | Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a&nbsp;third-party&nbsp;library | -&nbsp;[Standard&nbsp;System&nbsp;Porting&nbsp;Guide](porting/standard-system-porting-guide.md)<br/>-&nbsp;[A&nbsp;Method&nbsp;for&nbsp;Rapidly&nbsp;Porting&nbsp;the&nbsp;OpenHarmony&nbsp;Linux&nbsp;Kernel](porting/porting-linux-kernel.md) |
| Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) | | Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) |
| Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | -&nbsp;[API&nbsp;References](https://gitee.com/link?target=https%3A%2F%2Fdevice.harmonyos.com%2Fen%2Fdocs%2Fapiref%2Fjs-framework-file-0000000000616658)<br/>-&nbsp;[FAQs](faqs/faqs-overview.md) | Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md)
...@@ -44,7 +44,7 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 ...@@ -44,7 +44,7 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按
| 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[WLAN连接类产品](guide/device-wlan-led-control.md)<br/>-&nbsp;[无屏摄像头类产品](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[带屏摄像头类产品](guide/device-camera-control-overview.md) | | 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[WLAN连接类产品](guide/device-wlan-led-control.md)<br/>-&nbsp;[无屏摄像头类产品](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[带屏摄像头类产品](guide/device-camera-control-overview.md) |
| 移植适配 | -&nbsp;针对特定芯片做移植适配<br/>-&nbsp;对三方库进行移植适配 | -&nbsp;[轻量系统芯片移植指导](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md) | | 移植适配 | -&nbsp;针对特定芯片做移植适配<br/>-&nbsp;对三方库进行移植适配 | -&nbsp;[轻量系统芯片移植指导](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[小型系统芯片移植指导](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[轻量和小型系统三方库移植指导](porting/porting-thirdparty-overview.md) |
| 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) | | 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) |
| 参考 | 开发参考 | -&nbsp;[API参考](https://gitee.com/link?target=https%3A%2F%2Fdevice.harmonyos.com%2Fcn%2Fdocs%2Fdevelop%2Fapiref%2Fjs-framework-file-0000000000611396)<br/>-&nbsp;[常见问题](faqs/faqs-overview.md) | | 参考 | 开发参考 | [常见问题](faqs/faqs-overview.md) |
**表 2** 标准系统开发指导(参考内存≥128MB) **表 2** 标准系统开发指导(参考内存≥128MB)
...@@ -57,4 +57,4 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按 ...@@ -57,4 +57,4 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按
| 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[时钟应用开发指导](guide/device-clock-guide.md)<br/>-&nbsp;[平台驱动开发示例](guide/device-driver-demo.md)<br/>-&nbsp;[外设驱动开发示例](guide/device-outerdriver-demo.md) | | 进阶开发 | 结合系统能力开发智能设备 | -&nbsp;[时钟应用开发指导](guide/device-clock-guide.md)<br/>-&nbsp;[平台驱动开发示例](guide/device-driver-demo.md)<br/>-&nbsp;[外设驱动开发示例](guide/device-outerdriver-demo.md) |
| 移植适配 | 对三方库进行移植适配 | -&nbsp;[标准系统芯片移植指导](porting/standard-system-porting-guide.md)<br/>-&nbsp;[一种快速移植OpenHarmony&nbsp;Linux内核的方法](porting/porting-linux-kernel.md) | | 移植适配 | 对三方库进行移植适配 | -&nbsp;[标准系统芯片移植指导](porting/standard-system-porting-guide.md)<br/>-&nbsp;[一种快速移植OpenHarmony&nbsp;Linux内核的方法](porting/porting-linux-kernel.md) |
| 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) | | 贡献组件 | 为OpenHarmony贡献功能组件 | -&nbsp;[HPM&nbsp;Part&nbsp;介绍](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;开发指导](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM&nbsp;Part&nbsp;参考](hpm-part/hpm-part-reference.md) |
| 参考 | 开发参考 | -&nbsp;[API参考](https://gitee.com/link?target=https%3A%2F%2Fdevice.harmonyos.com%2Fcn%2Fdocs%2Fdevelop%2Fapiref%2Fjs-framework-file-0000000000611396)<br/>-&nbsp;[常见问题](faqs/faqs-overview.md) | | 参考 | 开发参考 |[常见问题](faqs/faqs-overview.md) |
...@@ -34,8 +34,7 @@ ...@@ -34,8 +34,7 @@
- [LMS调测](kernel-mini-memory-lms.md) - [LMS调测](kernel-mini-memory-lms.md)
- 附录 - 附录
- [内核编码规范](kernel-mini-appx-code.md) - [内核编码规范](kernel-mini-appx-code.md)
- 基本数据结构 - [双向链表](kernel-mini-appx-data-list.md)
- [双向链表](kernel-mini-appx-data-list.md)
- 标准库支持 - 标准库支持
- [CMSIS支持](kernel-mini-appx-lib-cmsis.md) - [CMSIS支持](kernel-mini-appx-lib-cmsis.md)
- [POSIX支持](kernel-mini-appx-lib-posix.md) - [POSIX支持](kernel-mini-appx-lib-posix.md)
...@@ -179,8 +178,7 @@ ...@@ -179,8 +178,7 @@
- [开发板Patch使用指导](kernel-standard-patch.md) - [开发板Patch使用指导](kernel-standard-patch.md)
- [Linux内核编译与构建指导](kernel-standard-build.md) - [Linux内核编译与构建指导](kernel-standard-build.md)
- [内核增强特性](kernel-standard-enhanced-features.md) - [内核增强特性](kernel-standard-enhanced-features.md)
- [内存管理](kernel-standard-mm.md) - [Enhanced SWAP特性介绍](kernel-standard-mm-eswap.md)
- [Enhanced SWAP特性介绍](kernel-standard-mm-eswap.md)
- [任务调度](kernel-standard-sched.md) - [任务调度](kernel-standard-sched.md)
- [关联线程组调度](kernel-standard-sched-rtg.md) - [关联线程组调度](kernel-standard-sched-rtg.md)
- [CPU轻量级隔离](kernel-standard-sched-cpuisolation.md) - [CPU轻量级隔离](kernel-standard-sched-cpuisolation.md)
...@@ -61,6 +61,7 @@ typedef struct tagEvent { ...@@ -61,6 +61,7 @@ typedef struct tagEvent {
**事件销毁**:销毁指定的事件控制块。 **事件销毁**:销毁指定的事件控制块。
**图1** 轻量系统事件运作原理图 **图1** 轻量系统事件运作原理图
![zh-cn_image_0000001200771972](figures/zh-cn_image_0000001200771972.png) ![zh-cn_image_0000001200771972](figures/zh-cn_image_0000001200771972.png)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。
**图1** 轻量系统互斥锁运作示意图 **图1** 轻量系统互斥锁运作示意图
![zh-cn_image_0000001245411845](figures/zh-cn_image_0000001245411845.png) ![zh-cn_image_0000001245411845](figures/zh-cn_image_0000001245411845.png)
......
...@@ -82,6 +82,7 @@ typedef struct ...@@ -82,6 +82,7 @@ typedef struct
- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 - 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。
**图1** 队列读写数据操作示意图 **图1** 队列读写数据操作示意图
![zh-cn_image_0000001200452026](figures/zh-cn_image_0000001200452026.png) ![zh-cn_image_0000001200452026](figures/zh-cn_image_0000001200452026.png)
上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。
......
...@@ -61,6 +61,7 @@ typedef struct { ...@@ -61,6 +61,7 @@ typedef struct {
信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。
**图1** 轻量系统信号量运作示意图 **图1** 轻量系统信号量运作示意图
![zh-cn_image_0000001245051881](figures/zh-cn_image_0000001245051881.png) ![zh-cn_image_0000001245051881](figures/zh-cn_image_0000001245051881.png)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下:
**图1** 轻量系统动态内存核心算法 **图1** 轻量系统动态内存核心算法
![zh-cn_image_0000001199352445](figures/zh-cn_image_0000001199352445.png) ![zh-cn_image_0000001199352445](figures/zh-cn_image_0000001199352445.png)
$$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示: $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示:
...@@ -28,6 +29,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 ...@@ -28,6 +29,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内
内存管理结构如下图所示: 内存管理结构如下图所示:
**图2** 轻量系统动态内存管理结构图 **图2** 轻量系统动态内存管理结构图
![zh-cn_image_0000001153313284](figures/zh-cn_image_0000001153313284.png) ![zh-cn_image_0000001153313284](figures/zh-cn_image_0000001153313284.png)
- 内存池池头部分 - 内存池池头部分
...@@ -39,6 +41,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 ...@@ -39,6 +41,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内
一些芯片片内RAM大小无法满足要求,需要使用片外物理内存进行扩充。对于这样的多段非连续性内存, LiteOS-M内核支持把多个非连续性内存逻辑上合一,用户不感知底层的多段非连续性内存区域。 LiteOS-M内核内存模块把不连续的内存区域作为空闲内存结点插入到空闲内存节点链表,把不同内存区域间的不连续部分标记为虚拟的已使用内存节点,从逻辑上把多个非连续性内存区域实现为一个统一的内存池。下面通过示意图说明下多段非连续性内存的运行机制: 一些芯片片内RAM大小无法满足要求,需要使用片外物理内存进行扩充。对于这样的多段非连续性内存, LiteOS-M内核支持把多个非连续性内存逻辑上合一,用户不感知底层的多段非连续性内存区域。 LiteOS-M内核内存模块把不连续的内存区域作为空闲内存结点插入到空闲内存节点链表,把不同内存区域间的不连续部分标记为虚拟的已使用内存节点,从逻辑上把多个非连续性内存区域实现为一个统一的内存池。下面通过示意图说明下多段非连续性内存的运行机制:
**图3** 非连续性内存合一示意图 **图3** 非连续性内存合一示意图
![zh-cn_image_0000001198253551](figures/zh-cn_image_0000001198253551.png) ![zh-cn_image_0000001198253551](figures/zh-cn_image_0000001198253551.png)
结合上述示意图,非连续性内存合并为一个统一的内存池的步骤如下: 结合上述示意图,非连续性内存合并为一个统一的内存池的步骤如下:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
静态内存池由一个控制块LOS_MEMBOX_INFO和若干相同大小的内存块LOS_MEMBOX_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 静态内存池由一个控制块LOS_MEMBOX_INFO和若干相同大小的内存块LOS_MEMBOX_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。
**图1** 静态内存示意图 **图1** 静态内存示意图
![zh-cn_image_0000001199352039](figures/zh-cn_image_0000001199352039.png) ![zh-cn_image_0000001199352039](figures/zh-cn_image_0000001199352039.png)
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
在硬件资源有限的小设备中,需要通过算法的动态部署能力来解决无法同时部署多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF加载方案,方便拓展算法生态。LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库。如图1所示,APP需要通过三方算法库所需接口获取对应信息输出,三方算法库又依赖内核提供的基本接口,如malloc等。APP加载所需接口,并对相关的未定义符号完成重定位后,APP即可调用该接口完成功能调用。目前动态加载组件只支持arm架构。此外,待加载的共享库需要验签或者限制来源,确保系统的安全性。 在硬件资源有限的小设备中,需要通过算法的动态部署能力来解决无法同时部署多种算法的问题。以开发者易用为主要考虑因素,同时考虑到多平台的通用性,LiteOS-M选择业界标准的ELF加载方案,方便拓展算法生态。LiteOS-M提供类似于dlopen、dlsym等接口,APP通过动态加载模块提供的接口可以加载、卸载相应算法库。如图1所示,APP需要通过三方算法库所需接口获取对应信息输出,三方算法库又依赖内核提供的基本接口,如malloc等。APP加载所需接口,并对相关的未定义符号完成重定位后,APP即可调用该接口完成功能调用。目前动态加载组件只支持arm架构。此外,待加载的共享库需要验签或者限制来源,确保系统的安全性。
**图1** LiteOS-M内核动态加载架构图 **图1** LiteOS-M内核动态加载架构图
![zh-cn_image_0000001200292052](figures/zh-cn_image_0000001200292052.png) ![zh-cn_image_0000001200292052](figures/zh-cn_image_0000001200292052.png)
...@@ -38,6 +39,7 @@ const SymInfo sym_##func __attribute__((section(".sym."#func))) = { \ ...@@ -38,6 +39,7 @@ const SymInfo sym_##func __attribute__((section(".sym."#func))) = { \
``` ```
**图2** 导出的符号表信息 **图2** 导出的符号表信息
![zh-cn_image_0000001245171875](figures/zh-cn_image_0000001245171875.png) ![zh-cn_image_0000001245171875](figures/zh-cn_image_0000001245171875.png)
...@@ -67,6 +69,7 @@ Program Headers: ...@@ -67,6 +69,7 @@ Program Headers:
``` ```
**图3** ELF文件的加载过程 **图3** ELF文件的加载过程
![zh-cn_image_0000001245251887](figures/zh-cn_image_0000001245251887.png) ![zh-cn_image_0000001245251887](figures/zh-cn_image_0000001245251887.png)
...@@ -75,6 +78,7 @@ Program Headers: ...@@ -75,6 +78,7 @@ Program Headers:
如图4所示,通过ELF文件的.dynamic段获取重定位表,遍历表中每一个需要重定位的条目,再根据需要重定位的符号名在共享库和内核提供的导出符号表中查找相应符号并更新相应的重定位信息。 如图4所示,通过ELF文件的.dynamic段获取重定位表,遍历表中每一个需要重定位的条目,再根据需要重定位的符号名在共享库和内核提供的导出符号表中查找相应符号并更新相应的重定位信息。
**图4** ELF文件的链接过程 **图4** ELF文件的链接过程
![zh-cn_image_0000001200612006](figures/zh-cn_image_0000001200612006.png) ![zh-cn_image_0000001200612006](figures/zh-cn_image_0000001200612006.png)
......
...@@ -11,6 +11,7 @@ OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系 ...@@ -11,6 +11,7 @@ OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系
OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中硬件相关层按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;其他模块属于硬件无关层,其中基础内核模块提供基础能力,扩展模块提供网络、文件系统等组件能力,还提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中硬件相关层按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;其他模块属于硬件无关层,其中基础内核模块提供基础能力,扩展模块提供网络、文件系统等组件能力,还提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。
**图1** 内核架构图 **图1** 内核架构图
![zh-cn_image_0000001199351155](figures/zh-cn_image_0000001199351155.png) ![zh-cn_image_0000001199351155](figures/zh-cn_image_0000001199351155.png)
...@@ -34,4 +35,5 @@ LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M ...@@ -34,4 +35,5 @@ LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M
在开发板配置文件target_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程。 在开发板配置文件target_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程。
**图2** 内核启动流程 **图2** 内核启动流程
![zh-cn_image_0000001160338832](figures/zh-cn_image_0000001160338832.png) ![zh-cn_image_0000001160338832](figures/zh-cn_image_0000001160338832.png)
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。 以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。
**图1** 中断向量表 **图1** 中断向量表
![zh-cn_image_0000001199713709](figures/zh-cn_image_0000001199713709.png) ![zh-cn_image_0000001199713709](figures/zh-cn_image_0000001199713709.png)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
堆内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。OpenHarmony LiteOS-A堆内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: 堆内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。OpenHarmony LiteOS-A堆内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下:
**图1** 小型系统动态内存核心算法 **图1** 小型系统动态内存核心算法
![zh-cn_image_0000001146437734](figures/zh-cn_image_0000001146437734.png) ![zh-cn_image_0000001146437734](figures/zh-cn_image_0000001146437734.png)
$$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示: $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:[4, 127]和[2^{7}$, 2^{31}$],如上图size class所示:
...@@ -32,6 +33,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内 ...@@ -32,6 +33,7 @@ $$根据空闲内存块的大小,使用多个空闲链表来管理。根据内
内存管理结构如图2所示: 内存管理结构如图2所示:
**图2** 小型系统动态内存管理结构图 **图2** 小型系统动态内存管理结构图
![zh-cn_image_0000001180855455](figures/zh-cn_image_0000001180855455.png) ![zh-cn_image_0000001180855455](figures/zh-cn_image_0000001180855455.png)
- 内存池池头部分 - 内存池池头部分
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
如下图所示,LiteOS-A内核的物理内存使用分布视图,主要由内核镜像、内核堆及物理页组成。内核堆部分见堆内存管理一节。 如下图所示,LiteOS-A内核的物理内存使用分布视图,主要由内核镜像、内核堆及物理页组成。内核堆部分见堆内存管理一节。
**图1** 物理内存使用分布图 **图1** 物理内存使用分布图
![zh-cn_image_0000001179140185](figures/zh-cn_image_0000001179140185.png) ![zh-cn_image_0000001179140185](figures/zh-cn_image_0000001179140185.png)
伙伴算法把所有空闲页帧分成9个内存块组,每组中内存块包含2的幂次方个页帧,例如:第0组的内存块包含2的0次方个页帧,即1个页帧;第8组的内存块包含2的8次方个页帧,即256个页帧。相同大小的内存块挂在同一个链表上进行管理。 伙伴算法把所有空闲页帧分成9个内存块组,每组中内存块包含2的幂次方个页帧,例如:第0组的内存块包含2的0次方个页帧,即1个页帧;第8组的内存块包含2的8次方个页帧,即256个页帧。相同大小的内存块挂在同一个链表上进行管理。
...@@ -26,12 +27,14 @@ ...@@ -26,12 +27,14 @@
系统申请12KiB内存,即3个页帧时,9个内存块组中索引为3的链表挂着一块大小为8个页帧的内存块满足要求,分配出12KiB内存后还剩余20KiB内存,即5个页帧,将5个页帧分成2的幂次方之和,即4跟1,尝试查找伙伴进行合并。4个页帧的内存块没有伙伴则直接插到索引为2的链表上,继续查找1个页帧的内存块是否有伙伴,索引为0的链表上此时有1个,如果两个内存块地址连续则进行合并,并将内存块挂到索引为1的链表上,否则不做处理。 系统申请12KiB内存,即3个页帧时,9个内存块组中索引为3的链表挂着一块大小为8个页帧的内存块满足要求,分配出12KiB内存后还剩余20KiB内存,即5个页帧,将5个页帧分成2的幂次方之和,即4跟1,尝试查找伙伴进行合并。4个页帧的内存块没有伙伴则直接插到索引为2的链表上,继续查找1个页帧的内存块是否有伙伴,索引为0的链表上此时有1个,如果两个内存块地址连续则进行合并,并将内存块挂到索引为1的链表上,否则不做处理。
**图2** 内存申请示意图 **图2** 内存申请示意图
![zh-cn_image_0000001189778871](figures/zh-cn_image_0000001189778871.png) ![zh-cn_image_0000001189778871](figures/zh-cn_image_0000001189778871.png)
- 释放内存 - 释放内存
系统释放12KiB内存,即3个页帧,将3个页帧分成2的幂次方之和,即2跟1,尝试查找伙伴进行合并,索引为1的链表上有1个内存块,若地址连续则合并,并将合并后的内存块挂到索引为2的链表上,索引为0的链表上此时也有1个,如果地址连续则进行合并,并将合并后的内存块挂到索引为1的链表上,此时继续判断是否有伙伴,重复上述操作。 系统释放12KiB内存,即3个页帧,将3个页帧分成2的幂次方之和,即2跟1,尝试查找伙伴进行合并,索引为1的链表上有1个内存块,若地址连续则合并,并将合并后的内存块挂到索引为2的链表上,索引为0的链表上此时也有1个,如果地址连续则进行合并,并将合并后的内存块挂到索引为1的链表上,此时继续判断是否有伙伴,重复上述操作。
**图3** 内存释放示意图 **图3** 内存释放示意图
![zh-cn_image_0000001143739220](figures/zh-cn_image_0000001143739220.png) ![zh-cn_image_0000001143739220](figures/zh-cn_image_0000001143739220.png)
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
- CPU访问的虚拟地址所在的页,如V2,没有与具体的物理页做映射,系统会触发缺页异常,系统申请一个物理页,并把相应的信息拷贝到物理页中,并且把物理页的起始地址更新到页表条目中。此时CPU重新执行访问虚拟内存的指令便能够访问到具体的代码或数据。 - CPU访问的虚拟地址所在的页,如V2,没有与具体的物理页做映射,系统会触发缺页异常,系统申请一个物理页,并把相应的信息拷贝到物理页中,并且把物理页的起始地址更新到页表条目中。此时CPU重新执行访问虚拟内存的指令便能够访问到具体的代码或数据。
**图1** 内存映射示意图 **图1** 内存映射示意图
![zh-cn_image_0000001179142959](figures/zh-cn_image_0000001179142959.png) ![zh-cn_image_0000001179142959](figures/zh-cn_image_0000001179142959.png)
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
- 僵尸(Zombies):进程运行结束,等待父进程回收其控制块资源。 - 僵尸(Zombies):进程运行结束,等待父进程回收其控制块资源。
**图1** 进程状态迁移示意图 **图1** 进程状态迁移示意图
![zh-cn_image_0000001219007317](figures/zh-cn_image_0000001219007317.png) ![zh-cn_image_0000001219007317](figures/zh-cn_image_0000001219007317.png)
**进程状态迁移说明:** **进程状态迁移说明:**
...@@ -73,6 +74,7 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离, ...@@ -73,6 +74,7 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,
进程只是资源管理单元,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。 进程只是资源管理单元,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。
**图2** 进程管理示意图 **图2** 进程管理示意图
![zh-cn_image_0000001199736949](figures/zh-cn_image_0000001199736949.png) ![zh-cn_image_0000001199736949](figures/zh-cn_image_0000001199736949.png)
......
...@@ -22,11 +22,13 @@ OpenHarmony 调度的最小单元为线程。 ...@@ -22,11 +22,13 @@ OpenHarmony 调度的最小单元为线程。
OpenHarmony 采用进程优先级队列+线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。 OpenHarmony 采用进程优先级队列+线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。
**图1** 调度优先级桶队列示意图 **图1** 调度优先级桶队列示意图
![zh-cn_image_0000001199705711](figures/zh-cn_image_0000001199705711.png) ![zh-cn_image_0000001199705711](figures/zh-cn_image_0000001199705711.png)
OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中创建的进程或线程会被加入到调度队列,系统根据进程和线程的优先级及线程的时间片消耗情况选择最优的线程进行调度运行,线程一旦调度到就会从调度队列上删除,线程在运行过程中发生阻塞,会被加入到对应的阻塞队列中并触发一次调度,调度其它线程运行。如果调度队列上没有可以调度的线程,则系统就会选择KIdle进程的线程进行调度运行。 OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中创建的进程或线程会被加入到调度队列,系统根据进程和线程的优先级及线程的时间片消耗情况选择最优的线程进行调度运行,线程一旦调度到就会从调度队列上删除,线程在运行过程中发生阻塞,会被加入到对应的阻塞队列中并触发一次调度,调度其它线程运行。如果调度队列上没有可以调度的线程,则系统就会选择KIdle进程的线程进行调度运行。
**图2** 调度流程示意图 **图2** 调度流程示意图
![zh-cn_image_0000001199706239](figures/zh-cn_image_0000001199706239.png) ![zh-cn_image_0000001199706239](figures/zh-cn_image_0000001199706239.png)
......
...@@ -34,6 +34,7 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0 ...@@ -34,6 +34,7 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0
- 退出(Exit):任务运行结束,等待父任务回收其控制块资源。 - 退出(Exit):任务运行结束,等待父任务回收其控制块资源。
**图1** 任务状态迁移示意图 **图1** 任务状态迁移示意图
![zh-cn_image_0000001173399977](figures/zh-cn_image_0000001173399977.png) ![zh-cn_image_0000001173399977](figures/zh-cn_image_0000001173399977.png)
**任务状态迁移说明:** **任务状态迁移说明:**
......
...@@ -74,6 +74,7 @@ typedef struct tagEvent { ...@@ -74,6 +74,7 @@ typedef struct tagEvent {
**事件销毁**:销毁指定的事件控制块。 **事件销毁**:销毁指定的事件控制块。
**图1** 小型系统事件运作原理图 **图1** 小型系统事件运作原理图
![zh-cn_image_0000001180952545](figures/zh-cn_image_0000001180952545.png) ![zh-cn_image_0000001180952545](figures/zh-cn_image_0000001180952545.png)
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。
**图1** 小型系统互斥锁运作示意图 **图1** 小型系统互斥锁运作示意图
![zh-cn_image_0000001177654887](figures/zh-cn_image_0000001177654887.png) ![zh-cn_image_0000001177654887](figures/zh-cn_image_0000001177654887.png)
......
# 消息队列 # 消息队列
- [基本概念](#基本概念) - [基本概念](#基本概念)
- [运行机制](#运行机制) - [运行机制](#运行机制)
- [队列控制块](#队列控制块) - [队列控制块](#队列控制块)
- [队列运作原理](#队列运作原理) - [队列运作原理](#队列运作原理)
- [开发指导](#开发指导) - [开发指导](#开发指导)
- [接口说明](#接口说明) - [接口说明](#接口说明)
- [开发流程](#开发流程) - [开发流程](#开发流程)
- [编程实例](#编程实例) - [编程实例](#编程实例)
- [实例描述](#实例描述) - [实例描述](#实例描述)
- [编程示例](#编程示例) - [编程示例](#编程示例)
- [结果验证](#结果验证) - [结果验证](#结果验证)
## 基本概念 ## 基本概念
队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。
任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。
可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。
消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: 消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性:
- 消息以先进先出的方式排队,支持异步读写。 - 消息以先进先出的方式排队,支持异步读写。
- 读队列和写队列都支持超时机制。 - 读队列和写队列都支持超时机制。
- 每读取一条消息,就会将该消息节点设置为空闲。 - 每读取一条消息,就会将该消息节点设置为空闲。
- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 - 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。
- 一个任务能够从任意一个消息队列接收和发送消息。 - 一个任务能够从任意一个消息队列接收和发送消息。
- 多个任务能够从同一个消息队列接收和发送消息。 - 多个任务能够从同一个消息队列接收和发送消息。
- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 - 创建队列时所需的队列空间,接口内系统自行动态申请内存。
## 运行机制 ## 运行机制
### 队列控制块 ### 队列控制块
``` ```
/** /**
* 队列控制块数据结构 * 队列控制块数据结构
*/ */
typedef struct { typedef struct {
UINT8 *queueHandle; /**< Pointer to a queue handle */ UINT8 *queueHandle; /**< Pointer to a queue handle */
UINT16 queueState; /**< Queue state */ UINT16 queueState; /**< Queue state */
UINT16 queueLen; /**< Queue length */ UINT16 queueLen; /**< Queue length */
UINT16 queueSize; /**< Node size */ UINT16 queueSize; /**< Node size */
UINT32 queueID; /**< queueID */ UINT32 queueID; /**< queueID */
UINT16 queueHead; /**< Node head */ UINT16 queueHead; /**< Node head */
UINT16 queueTail; /**< Node tail */ UINT16 queueTail; /**< Node tail */
UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */ UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /**< Count of readable or writable resources, 0:readable, 1:writable */
LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */ LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */
LOS_DL_LIST memList; /**< Pointer to the memory linked list */ LOS_DL_LIST memList; /**< Pointer to the memory linked list */
} LosQueueCB; } LosQueueCB;
``` ```
每个队列控制块中都含有队列状态,表示该队列的使用情况: 每个队列控制块中都含有队列状态,表示该队列的使用情况:
- OS_QUEUE_UNUSED:队列未被使用。 - OS_QUEUE_UNUSED:队列未被使用。
- OS_QUEUE_INUSED:队列被使用中。 - OS_QUEUE_INUSED:队列被使用中。
### 队列运作原理 ### 队列运作原理
- 创建队列时,创建队列成功会返回队列ID。 - 创建队列时,创建队列成功会返回队列ID。
- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 - 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。
- 写队列时,根据readWriteableCnt[1]判断队列是否可以写入,不能对已满(readWriteableCnt[1]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 - 写队列时,根据readWriteableCnt[1]判断队列是否可以写入,不能对已满(readWriteableCnt[1]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。
- 读队列时,根据readWriteableCnt[0]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt[0]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 - 读队列时,根据readWriteableCnt[0]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt[0]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。
- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 - 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。
**图1** 队列读写数据操作示意图 **图1** 队列读写数据操作示意图
![zh-cn_image_0000001132875772](figures/zh-cn_image_0000001132875772.png)
![zh-cn_image_0000001132875772](figures/zh-cn_image_0000001132875772.png)
上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。
上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。
## 开发指导
## 开发指导
### 接口说明
### 接口说明
| 功能分类 | 接口**名称** | 描述 |
| -------- | -------- | -------- | | 功能分类 | 接口**名称** | 描述 |
| 创建/删除消息队列 | LOS_QueueCreate | 创建一个消息队列,由系统动态申请队列空间 | | -------- | -------- | -------- |
| | LOS_QueueDelete |根据队列ID删除一个指定队列| | 创建/删除消息队列 | LOS_QueueCreate | 创建一个消息队列,由系统动态申请队列空间 |
| 读/写队列(不带拷贝) | LOS_QueueRead | 读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址) | | | LOS_QueueDelete |根据队列ID删除一个指定队列|
| | LOS_QueueWrite |向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)| | 读/写队列(不带拷贝) | LOS_QueueRead | 读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址) |
| | LOS_QueueWriteHead |向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)| | | LOS_QueueWrite |向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)|
| 读/写队列(带拷贝) | LOS_QueueReadCopy | 读取指定队列头节点中的数据 | | | LOS_QueueWriteHead |向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)|
| | LOS_QueueWriteCopy |向指定队列尾节点中写入入参bufferAddr中保存的数据| | 读/写队列(带拷贝) | LOS_QueueReadCopy | 读取指定队列头节点中的数据 |
| | LOS_QueueWriteHeadCopy |向指定队列头节点中写入入参bufferAddr中保存的数据| | | LOS_QueueWriteCopy |向指定队列尾节点中写入入参bufferAddr中保存的数据|
| 获取队列信息 | LOS_QueueInfoGet | 获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务 | | | LOS_QueueWriteHeadCopy |向指定队列头节点中写入入参bufferAddr中保存的数据|
| 获取队列信息 | LOS_QueueInfoGet | 获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务 |
### 开发流程
### 开发流程
1. 用LOS_QueueCreate创建队列。创建成功后,可以得到队列ID。
1. 用LOS_QueueCreate创建队列。创建成功后,可以得到队列ID。
2. 通过LOS_QueueWrite或者LOS_QueueWriteCopy写队列。
2. 通过LOS_QueueWrite或者LOS_QueueWriteCopy写队列。
3. 通过LOS_QueueRead或者LOS_QueueReadCopy读队列。
3. 通过LOS_QueueRead或者LOS_QueueReadCopy读队列。
4. 通过LOS_QueueInfoGet获取队列信息。
4. 通过LOS_QueueInfoGet获取队列信息。
5. 通过LOS_QueueDelete删除队列。
5. 通过LOS_QueueDelete删除队列。
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> - 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> > - 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。
> - 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 >
> > - 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。
> - 队列接口函数中的入参timeOut是相对时间。 >
> > - 队列接口函数中的入参timeOut是相对时间。
> - LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,每组接口需要配套使用。 >
> > - LOS_QueueReadCopy和LOS_QueueWriteCopy及LOS_QueueWriteHeadCopy是一组接口,LOS_QueueRead和LOS_QueueWrite及LOS_QueueWriteHead是一组接口,每组接口需要配套使用。
> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 >
> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。
> >
> - LOS_QueueRead和LOS_QueueReadCopy接口的读取长度如果小于消息实际长度,消息将被截断。 > - LOS_QueueRead和LOS_QueueReadCopy接口的读取长度如果小于消息实际长度,消息将被截断。
> >
> - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 > - 鉴于LOS_QueueWrite和LOS_QueueWriteHead和LOS_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。
## 编程实例 ## 编程实例
### 实例描述 ### 实例描述
创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。
1. 通过LOS_TaskCreate创建任务1和任务2。 1. 通过LOS_TaskCreate创建任务1和任务2。
2. 通过LOS_QueueCreate创建一个消息队列。 2. 通过LOS_QueueCreate创建一个消息队列。
3. 在任务1 SendEntry中发送消息。 3. 在任务1 SendEntry中发送消息。
4. 在任务2 RecvEntry中接收消息。 4. 在任务2 RecvEntry中接收消息。
5. 通过LOS_QueueDelete删除队列。 5. 通过LOS_QueueDelete删除队列。
### 编程示例 ### 编程示例
示例代码如下: 示例代码如下:
``` ```
#include "los_task.h" #include "los_task.h"
#include "los_queue.h" #include "los_queue.h"
static UINT32 g_queue; static UINT32 g_queue;
#define BUFFER_LEN 50 #define BUFFER_LEN 50
VOID SendEntry(VOID) VOID SendEntry(VOID)
{ {
UINT32 ret = 0; UINT32 ret = 0;
CHAR abuf[] = "test message"; CHAR abuf[] = "test message";
UINT32 len = sizeof(abuf); UINT32 len = sizeof(abuf);
ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("send message failure, error: %x\n", ret); printf("send message failure, error: %x\n", ret);
} }
} }
VOID RecvEntry(VOID) VOID RecvEntry(VOID)
{ {
UINT32 ret = 0; UINT32 ret = 0;
CHAR readBuf[BUFFER_LEN] = {0}; CHAR readBuf[BUFFER_LEN] = {0};
UINT32 readLen = BUFFER_LEN; UINT32 readLen = BUFFER_LEN;
//休眠1s //休眠1s
usleep(1000000); usleep(1000000);
ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("recv message failure, error: %x\n", ret); printf("recv message failure, error: %x\n", ret);
} }
printf("recv message: %s\n", readBuf); printf("recv message: %s\n", readBuf);
ret = LOS_QueueDelete(g_queue); ret = LOS_QueueDelete(g_queue);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("delete the queue failure, error: %x\n", ret); printf("delete the queue failure, error: %x\n", ret);
} }
printf("delete the queue success!\n"); printf("delete the queue success!\n");
} }
UINT32 ExampleQueue(VOID) UINT32 ExampleQueue(VOID)
{ {
printf("start queue example\n"); printf("start queue example\n");
UINT32 ret = 0; UINT32 ret = 0;
UINT32 task1, task2; UINT32 task1, task2;
TSK_INIT_PARAM_S initParam = {0}; TSK_INIT_PARAM_S initParam = {0};
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry;
initParam.usTaskPrio = 9; initParam.usTaskPrio = 9;
initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
initParam.pcName = "SendQueue"; initParam.pcName = "SendQueue";
LOS_TaskLock(); LOS_TaskLock();
ret = LOS_TaskCreate(&task1, &initParam); ret = LOS_TaskCreate(&task1, &initParam);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("create task1 failed, error: %x\n", ret); printf("create task1 failed, error: %x\n", ret);
return ret; return ret;
} }
initParam.pcName = "RecvQueue"; initParam.pcName = "RecvQueue";
initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry;
ret = LOS_TaskCreate(&task2, &initParam); ret = LOS_TaskCreate(&task2, &initParam);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("create task2 failed, error: %x\n", ret); printf("create task2 failed, error: %x\n", ret);
return ret; return ret;
} }
ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50);
if(ret != LOS_OK) { if(ret != LOS_OK) {
printf("create queue failure, error: %x\n", ret); printf("create queue failure, error: %x\n", ret);
} }
printf("create the queue success!\n"); printf("create the queue success!\n");
LOS_TaskUnlock(); LOS_TaskUnlock();
return ret; return ret;
} }
``` ```
### 结果验证 ### 结果验证
编译运行得到的结果为: 编译运行得到的结果为:
``` ```
start test example start test example
create the queue success! create the queue success!
recv message: test message recv message: test message
delete the queue success! delete the queue success!
``` ```
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
运行示意图如下图所示: 运行示意图如下图所示:
**图1** 小型系统信号量运作示意图 **图1** 小型系统信号量运作示意图
![zh-cn_image_0000001132774752](figures/zh-cn_image_0000001132774752.png) ![zh-cn_image_0000001132774752](figures/zh-cn_image_0000001132774752.png)
......
...@@ -19,6 +19,7 @@ Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种 ...@@ -19,6 +19,7 @@ Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种
当前哈希桶共有80个,0~63号桶用于存放私有锁(以虚拟地址进行哈希),64~79号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。 当前哈希桶共有80个,0~63号桶用于存放私有锁(以虚拟地址进行哈希),64~79号桶用于存放共享锁(以物理地址进行哈希),私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。
**图1** Futex设计图 **图1** Futex设计图
![zh-cn_image_0000001127535690](figures/zh-cn_image_0000001127535690.jpg) ![zh-cn_image_0000001127535690](figures/zh-cn_image_0000001127535690.jpg)
如图1,每个futex哈希桶中存放被futex_list串联起来的哈希值相同的futex node,每个futex node对应一个被挂起的task,node中key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。 如图1,每个futex哈希桶中存放被futex_list串联起来的哈希值相同的futex node,每个futex node对应一个被挂起的task,node中key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。
......
...@@ -22,6 +22,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 ...@@ -22,6 +22,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及
## 运行机制 ## 运行机制
**图1** 动态加载流程 **图1** 动态加载流程
![zh-cn_image_0000001133104502](figures/zh-cn_image_0000001133104502.png) ![zh-cn_image_0000001133104502](figures/zh-cn_image_0000001133104502.png)
1. 内核将应用程序ELF文件的PT_LOAD段信息映射至进程空间。对于ET_EXEC类型的文件,根据PT_LOAD段中p_vaddr进行固定地址映射;对于ET_DYN类型(位置无关的可执行程序,通过编译选项“-fPIE”得到)的文件,内核通过mmap接口选择base基址进行映射(load_addr = base + p_vaddr)。 1. 内核将应用程序ELF文件的PT_LOAD段信息映射至进程空间。对于ET_EXEC类型的文件,根据PT_LOAD段中p_vaddr进行固定地址映射;对于ET_DYN类型(位置无关的可执行程序,通过编译选项“-fPIE”得到)的文件,内核通过mmap接口选择base基址进行映射(load_addr = base + p_vaddr)。
...@@ -31,6 +32,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及 ...@@ -31,6 +32,7 @@ OpenHarmony系统的动态加载与链接机制主要是由内核加载器以及
3. 动态链接器自举并查找应用程序依赖的所有共享库并对导入符号进行重定位,最后跳转至应用程序的e_entry(或base + e_entry),开始运行应用程序。 3. 动态链接器自举并查找应用程序依赖的所有共享库并对导入符号进行重定位,最后跳转至应用程序的e_entry(或base + e_entry),开始运行应用程序。
**图2** 程序执行流程 **图2** 程序执行流程
![zh-cn_image_0000001133264664](figures/zh-cn_image_0000001133264664.png) ![zh-cn_image_0000001133264664](figures/zh-cn_image_0000001133264664.png)
1. 加载器与链接器调用mmap映射PT_LOAD段; 1. 加载器与链接器调用mmap映射PT_LOAD段;
......
...@@ -21,6 +21,7 @@ VDSO总体可分为数据页与代码页两部分: ...@@ -21,6 +21,7 @@ VDSO总体可分为数据页与代码页两部分:
- 代码页提供屏蔽系统调用的主要逻辑; - 代码页提供屏蔽系统调用的主要逻辑;
**图1** VDSO系统设计 **图1** VDSO系统设计
![zh-cn_image_0000001173586763](figures/zh-cn_image_0000001173586763.jpg) ![zh-cn_image_0000001173586763](figures/zh-cn_image_0000001173586763.jpg)
如图1所示,当前VDSO机制有以下几个主要步骤: 如图1所示,当前VDSO机制有以下几个主要步骤:
......
...@@ -14,7 +14,9 @@ OpenHarmony LiteOS-A实现了用户态与内核态的区分隔离,用户态程 ...@@ -14,7 +14,9 @@ OpenHarmony LiteOS-A实现了用户态与内核态的区分隔离,用户态程
## 运行机制 ## 运行机制
如图1所示,用户程序通过调用System API(系统API,通常是系统提供的POSIX接口)进行内核资源访问与交互请求,POSIX接口内部会触发SVC/SWI异常,完成系统从用户态到内核态的切换,然后对接到内核的Syscall Handler(系统调用统一处理接口)进行参数解析,最终分发至具体的内核处理函数。 如图1所示,用户程序通过调用System API(系统API,通常是系统提供的POSIX接口)进行内核资源访问与交互请求,POSIX接口内部会触发SVC/SWI异常,完成系统从用户态到内核态的切换,然后对接到内核的Syscall Handler(系统调用统一处理接口)进行参数解析,最终分发至具体的内核处理函数。
**图1** 系统调用示意图 **图1** 系统调用示意图
![zh-cn_image_0000001132856572](figures/zh-cn_image_0000001132856572.png) ![zh-cn_image_0000001132856572](figures/zh-cn_image_0000001132856572.png)
Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA32SyscallHandle函数,在进入系统软中断异常时会调用此函数,并且按照kernel/liteos_a/syscall/syscall_lookup.h中的清单进行系统调用的入参解析,执行各系统调用最终对应的内核处理函数。 Syscall Handler的具体实现在kernel/liteos_a/syscall/los_syscall.c中OsArmA32SyscallHandle函数,在进入系统软中断异常时会调用此函数,并且按照kernel/liteos_a/syscall/syscall_lookup.h中的清单进行系统调用的入参解析,执行各系统调用最终对应的内核处理函数。
......
...@@ -13,11 +13,13 @@ ...@@ -13,11 +13,13 @@
释放内存时:根据需要释放的内存地址匹配内存节点控制块并将该控制块删除。 释放内存时:根据需要释放的内存地址匹配内存节点控制块并将该控制块删除。
**图1** 堆内存节点信息链表 **图1** 堆内存节点信息链表
![zh-cn_image_0000001165890158](figures/zh-cn_image_0000001165890158.png) ![zh-cn_image_0000001165890158](figures/zh-cn_image_0000001165890158.png)
申请内存时,返回地址会被保存到LR寄存器中。进程运行过程中,系统会在内存节点控制块中添加疑似泄漏点对应的lr等信息。如下图所示: 申请内存时,返回地址会被保存到LR寄存器中。进程运行过程中,系统会在内存节点控制块中添加疑似泄漏点对应的lr等信息。如下图所示:
**图2** 堆内存节点信息 **图2** 堆内存节点信息
![zh-cn_image_0000001165890518](figures/zh-cn_image_0000001165890518.png) ![zh-cn_image_0000001165890518](figures/zh-cn_image_0000001165890518.png)
其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr[n]表示函数调用栈地址,变量n可以根据具体场景的需要进行配置。 其中,TID表示线程ID;PID表示进程ID;ptr表示申请的内存地址;size表示申请的内存大小;lr[n]表示函数调用栈地址,变量n可以根据具体场景的需要进行配置。
...@@ -27,6 +29,7 @@ ...@@ -27,6 +29,7 @@
用户通过串口或文件等方式,将各个进程内存调测信息导出,利用addr2line工具将导出的信息转换成导致内存泄漏的代码行,便可以解决内存泄露问题。 用户通过串口或文件等方式,将各个进程内存调测信息导出,利用addr2line工具将导出的信息转换成导致内存泄漏的代码行,便可以解决内存泄露问题。
**图3** 泄漏点代码行定位流程 **图3** 泄漏点代码行定位流程
![zh-cn_image_0000001165730464](figures/zh-cn_image_0000001165730464.png) ![zh-cn_image_0000001165730464](figures/zh-cn_image_0000001165730464.png)
...@@ -41,15 +44,18 @@ ...@@ -41,15 +44,18 @@
用户程序申请堆内存时,在堆内存节点处添加校验值等信息,如果校验值异常,则很有可能是前一块堆内存使用越界导致的(目前无法识别校验值被野指针破坏的场景)。在内存申请、释放时校验内存节点校验值的正确性,若内存节点被破坏,校验失败时则输出tid、pid及当前被踩节点前一块堆内存申请时保存的调用栈信息,通过addr2line工具可获得具体的代码行信息,辅助用户解决问题。 用户程序申请堆内存时,在堆内存节点处添加校验值等信息,如果校验值异常,则很有可能是前一块堆内存使用越界导致的(目前无法识别校验值被野指针破坏的场景)。在内存申请、释放时校验内存节点校验值的正确性,若内存节点被破坏,校验失败时则输出tid、pid及当前被踩节点前一块堆内存申请时保存的调用栈信息,通过addr2line工具可获得具体的代码行信息,辅助用户解决问题。
**图4** node节点头信息添加校验值 **图4** node节点头信息添加校验值
![zh-cn_image_0000001211449151](figures/zh-cn_image_0000001211449151.png) ![zh-cn_image_0000001211449151](figures/zh-cn_image_0000001211449151.png)
free堆内存时,不会立即把该内存块释放掉,而是在内存中写入魔术数字0xFE,并放到free队列中(保证在一定时间内不会再被malloc函数分配),当有野指针或use-after-free的情况对该内存进行读取的操作时,能够发现数据异常,但是对于写操作则无法判断出来。 free堆内存时,不会立即把该内存块释放掉,而是在内存中写入魔术数字0xFE,并放到free队列中(保证在一定时间内不会再被malloc函数分配),当有野指针或use-after-free的情况对该内存进行读取的操作时,能够发现数据异常,但是对于写操作则无法判断出来。
**图5** free流程图 **图5** free流程图
![zh-cn_image_0000001165890904](figures/zh-cn_image_0000001165890904.png) ![zh-cn_image_0000001165890904](figures/zh-cn_image_0000001165890904.png)
- 使用malloc申请内存(大于0x1c000bytes时通过mmap申请) - 使用malloc申请内存(大于0x1c000bytes时通过mmap申请)
当malloc通过mmap申请大块内存时,在返回给用户使用的内存区间头和尾分别多申请一个页,一个页PAGE_SIZE当前为0x1000,这两个页分别通过mprotect接口设置权限为PROT_NONE(无可读可写权限),可以有效防止内存越界读写问题:越界读写数据时由于无读写权限而导致用户程序异常,根据异常调用栈信息可找到相应的代码逻辑。 当malloc通过mmap申请大块内存时,在返回给用户使用的内存区间头和尾分别多申请一个页,一个页PAGE_SIZE当前为0x1000,这两个页分别通过mprotect接口设置权限为PROT_NONE(无可读可写权限),可以有效防止内存越界读写问题:越界读写数据时由于无读写权限而导致用户程序异常,根据异常调用栈信息可找到相应的代码逻辑。
**图6** malloc通过mmap机制申请内存的内存布局 **图6** malloc通过mmap机制申请内存的内存布局
![zh-cn_image_0000001211130993](figures/zh-cn_image_0000001211130993.png) ![zh-cn_image_0000001211130993](figures/zh-cn_image_0000001211130993.png)
...@@ -30,6 +30,7 @@ OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawe ...@@ -30,6 +30,7 @@ OpenHarmony 轻量级内核是基于IoT领域轻量级物联网操作系统Huawe
轻量级内核主要由基础内核、扩展组件、HDF框架、POSIX接口组成。轻量级内核的文件系统、网络协议等扩展功能(没有像微内核那样运行在用户态)运行在内核地址空间,主要考虑组件之间直接函数调用比进程间通信或远程过程调用要快得多。 轻量级内核主要由基础内核、扩展组件、HDF框架、POSIX接口组成。轻量级内核的文件系统、网络协议等扩展功能(没有像微内核那样运行在用户态)运行在内核地址空间,主要考虑组件之间直接函数调用比进程间通信或远程过程调用要快得多。
**图1** OpenHarmony LiteOS-A内核架构图 **图1** OpenHarmony LiteOS-A内核架构图
![zh-cn_image_0000001160018656](figures/zh-cn_image_0000001160018656.png) ![zh-cn_image_0000001160018656](figures/zh-cn_image_0000001160018656.png)
- 基础内核主要包括内核的基础机制,如调度、内存管理、中断异常等 - 基础内核主要包括内核的基础机制,如调度、内存管理、中断异常等
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
**图1** 内核启动流程图 **图1** 内核启动流程图
![zh-cn_image_0000001153832492](figures/zh-cn_image_0000001153832492.png) ![zh-cn_image_0000001153832492](figures/zh-cn_image_0000001153832492.png)
......
...@@ -8,7 +8,7 @@ AI引擎框架包含client、server和common三个主要模块,其中client提 ...@@ -8,7 +8,7 @@ AI引擎框架包含client、server和common三个主要模块,其中client提
AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示:
**图 1** ****AI引擎代码依赖关系<a name="fig171811112818"></a> **图1** AI引擎代码依赖关系<a name="fig171811112818"></a>
![](figure/插件依赖-(2).jpg) ![](figure/插件依赖-(2).jpg)
......
...@@ -138,8 +138,7 @@ ...@@ -138,8 +138,7 @@
- [LMS调测](kernel/kernel-mini-memory-lms.md) - [LMS调测](kernel/kernel-mini-memory-lms.md)
- 附录 - 附录
- [内核编码规范](kernel/kernel-mini-appx-code.md) - [内核编码规范](kernel/kernel-mini-appx-code.md)
- 基本数据结构 - [双向链表](kernel/kernel-mini-appx-data-list.md)
- [双向链表](kernel/kernel-mini-appx-data-list.md)
- 标准库支持 - 标准库支持
- [CMSIS支持](kernel/kernel-mini-appx-lib-cmsis.md) - [CMSIS支持](kernel/kernel-mini-appx-lib-cmsis.md)
- [POSIX支持](kernel/kernel-mini-appx-lib-posix.md) - [POSIX支持](kernel/kernel-mini-appx-lib-posix.md)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册