目录
第16天:内存保护和安全
1. 内存保护的重要性
内存保护是指防止程序意外或恶意地访问和修改不属于它的内存区域。在嵌入式系统中,内存保护可以防止以下问题:
- 内存溢出:超出分配的内存范围,导致数据损坏或系统崩溃。
- 非法访问:访问未授权的内存区域,可能导致数据泄露或系统不稳定。
- 缓冲区溢出攻击:恶意攻击者利用缓冲区溢出漏洞,注入恶意代码。
2. FreeRTOS的内存保护机制
FreeRTOS提供了多种机制来增强内存保护和安全性。
2.1 内存管理单元(MMU)
内存管理单元(MMU)是一种硬件组件,用于管理虚拟地址和物理地址之间的映射。虽然大多数嵌入式处理器不包含完整的MMU,但许多处理器支持内存保护单元(MPU)。
2.2 内存保护单元(MPU)
内存保护单元(MPU)是一种轻量级的硬件组件,用于保护内存区域免受非法访问。FreeRTOS可以通过配置MPU来实现内存保护。
配置MPU
在FreeRTOS中,可以通过FreeRTOSConfig.h
文件中的配置选项来启用MPU支持:
C
深色版本
#define configUSE_MPU 1 // 启用MPU支持
示例代码
以下是一个示例代码,展示了如何在FreeRTOS中配置和使用MPU:
C
深色版本
#include "FreeRTOS.h"
#include "task.h"
#include "mpu_wrappers.h"
// 配置MPU区域
void configureMPURegions(void) {
MPU_REGION_Type MPURegion;
// 配置第一个MPU区域
MPURegion.BaseAddress = (uint32_t)sharedData;
MPURegion.RegionSize = MPU_REGION_SIZE_2KB;
MPURegion.AccessPermission = MPU_AP_NO_ACCESS; // 禁止访问
MPURegion.TypeExtField = MPU_TEX_LEVEL0;
MPURegion.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPURegion.SubRegionDisable = 0x00;
MPURegion.SizedRegion = 1;
MPU_SetRegion(&MPURegion);
// 配置第二个MPU区域
MPURegion.BaseAddress = (uint32_t)taskStack;
MPURegion.RegionSize = MPU_REGION_SIZE_1KB;
MPURegion.AccessPermission = MPU_AP_FULL_ACCESS; // 全部访问
MPURegion.TypeExtField = MPU_TEX_LEVEL0;
MPURegion.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPURegion.SubRegionDisable = 0x00;
MPURegion.SizedRegion = 1;
MPU_SetRegion(&MPURegion);
// 启用MPU
MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); // 启用MPU并启用默认存储器映射
}
// 任务函数
void vTaskFunction(void *pvParameters) {
while (1) {
// 任务代码
vTaskDelay(pdMS_TO_TICKS(1000));
printf("Task running\n");
}
}
int main(void) {
// 配置MPU区域
configureMPURegions();
// 创建任务
xTaskCreate(vTaskFunction, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
// 如果调度器返回,说明内存不足或任务创建失败
for (;;);
}
2.3 堆内存管理
FreeRTOS提供了多种堆内存管理方案,可以选择适合应用的方案来减少内存泄漏和碎片。
堆内存管理方案
FreeRTOS支持以下几种堆内存管理方案:
heap_1
:简单的内存分配器,不支持内存碎片合并。heap_2
:支持内存碎片合并,但不支持内存释放。heap_3
:使用标准C库的malloc
和free
函数。heap_4
:支持内存碎片合并和内存释放。heap_5
:支持内存碎片合并和内存释放,同时支持双堆内存区域。
配置堆内存管理方案
在FreeRTOSConfig.h
文件中,可以通过以下宏来选择堆内存管理方案:
C
深色版本
#define configUSE_HEAP_SCHEME heap_4 // 选择heap_4方案
3. 安全性增强措施
除了内存保护,还可以采取其他措施来增强系统的安全性。
3.1 任务堆栈保护
FreeRTOS提供了一个堆栈溢出检测机制,可以在任务堆栈溢出时触发异常。
配置堆栈溢出检测
在FreeRTOSConfig.h
文件中,可以通过以下宏来启用堆栈溢出检测:
C
深色版本
#define configCHECK_FOR_STACK_OVERFLOW 2 // 启用堆栈溢出检测
3.2 任务优先级保护
FreeRTOS提供了一个任务优先级保护机制,可以防止任务优先级被非法修改。
配置任务优先级保护
在FreeRTOSConfig.h
文件中,可以通过以下宏来启用任务优先级保护:
C
深色版本
#define configUSE_TASK Priorities 1 // 启用任务优先级保护
3.3 中断优先级保护
FreeRTOS提供了一个中断优先级保护机制,可以防止中断优先级被非法修改。
配置中断优先级保护
在FreeRTOSConfig.h
文件中,可以通过以下宏来启用中断优先级保护:
C
深色版本
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY) // 设置最大系统调用中断优先级
4. 示例代码
以下是一个综合示例,展示了如何在FreeRTOS中配置和使用内存保护和安全性增强措施:
C
深色版本
#include "FreeRTOS.h"
#include "task.h"
#include "mpu_wrappers.h"
#include <stdio.h>
// 共享数据
uint32_t sharedData[1024];
// 任务堆栈
uint32_t taskStack[1024];
// 配置MPU区域
void configureMPURegions(void) {
MPU_REGION_Type MPURegion;
// 配置第一个MPU区域
MPURegion.BaseAddress = (uint32_t)sharedData;
MPURegion.RegionSize = MPU_REGION_SIZE_2KB;
MPURegion.AccessPermission = MPU_AP_NO_ACCESS; // 禁止访问
MPURegion.TypeExtField = MPU_TEX_LEVEL0;
MPURegion.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPURegion.SubRegionDisable = 0x00;
MPURegion.SizedRegion = 1;
MPU_SetRegion(&MPURegion);
// 配置第二个MPU区域
MPURegion.BaseAddress = (uint32_t)taskStack;
MPURegion.RegionSize = MPU_REGION_SIZE_1KB;
MPURegion.AccessPermission = MPU_AP_FULL_ACCESS; // 全部访问
MPURegion.TypeExtField = MPU_TEX_LEVEL0;
MPURegion.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
MPURegion.SubRegionDisable = 0x00;
MPURegion.SizedRegion = 1;
MPU_SetRegion(&MPURegion);
// 启用MPU
MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); // 启用MPU并启用默认存储器映射
}
// 任务函数
void vTaskFunction(void *pvParameters) {
while (1) {
// 任务代码
vTaskDelay(pdMS_TO_TICKS(1000));
printf("Task running\n");
}
}
int main(void) {
// 配置MPU区域
configureMPURegions();
// 创建任务
xTaskCreate(vTaskFunction, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
// 如果调度器返回,说明内存不足或任务创建失败
for (;;);
}
5. 小结
通过今天的学习,你应该能够理解和掌握FreeRTOS在内存保护和安全方面的机制和配置方法。以下是总结的关键点:
- 内存保护的重要性:了解内存保护在嵌入式系统中的重要性。
- 内存保护单元(MPU):使用MPU配置和保护内存区域。
- 堆内存管理:选择合适的堆内存管理方案,减少内存泄漏和碎片。
- 安全性增强措施:启用堆栈溢出检测、任务优先级保护和中断优先级保护。
作业
-
配置MPU:
- 编写一个FreeRTOS应用程序,配置MPU保护共享数据区域。
- 观察任务对共享数据的访问情况,确保数据的安全性。
-
堆栈溢出检测:
- 编写一个FreeRTOS应用程序,启用堆栈溢出检测。
- 故意触发堆栈溢出,观察系统的异常处理情况。
-
任务优先级保护:
- 编写一个FreeRTOS应用程序,启用任务优先级保护。
- 尝试修改任务优先级,观察系统的保护机制是否生效。
-
思考题:
- 在嵌入式系统中,如何选择合适的内存保护和安全措施?
- 如何平衡内存保护和系统性能之间的关系?