嵌入式面试八股文(十四)·内存管理机制、优先级继承机制以及优先级翻转
目录
1. 内存管理算法(五种内存管理机制)
1.1 heap_1.c
1.2 heap_2.c
1.3 heap_3.c
1.4 heap_4.c
1.5 heap_5.c
1.6 总结
2. STM32通知寄存器有哪些?
2.1 核心寄存器组(Cortex-M)
2.2 特殊功能寄存器(需专用指令访问)
3. 什么是优先级翻转?
4. 什么是优先级继承?
1. 内存管理算法(五种内存管理机制)
在FreeRTOS定义了一个很大的全局数组ucHeap[configTOTAL_HEAP_SIZE],从这个数组里分配内存:
1.1 heap_1.c
最简单,不允许释放内存,只分配不删除,只有pvPortMalloc,没有实现vPortFree。
适用于比较简单的,一次性分配好内存的任务。
1.2 heap_2.c
最佳匹配算法,允许释放内存,但不会合并相邻的空闲块。
如图,heap_2.c会找到大小最为接近的内存块进行切割,如果多次分配,最终会导致碎片化严重。
1.3 heap_3.c
简单包装了标准 malloc() 和 free() ,configTOTAL_HEAP_SIZE不再起作用,以确保线程到的安全。
注:C库里的malloc、free函数并非线程安全的,Heap_3中先暂停FreeRTOS的调度器,再去调用这些函数,使用这种方法实现了线程安全。
1.4 heap_4.c
合并相邻的空闲块以避免碎片化,包含绝对地址放置选项。
1.5 heap_5.c
如同 heap_4,能够跨越多个不相邻内存区域的堆。
1.6 总结
方案 | 内存分配策略 | 碎片处理 | 适用场景 |
---|---|---|---|
heap_1.c | 静态分配,不可释放 | 无 | 仅需一次性分配的任务 |
heap_2.c | 最佳匹配算法,允许释放 | 中等 | 简单动态分配 |
heap_3.c | 封装标准库malloc/free | 依赖库 | 需要兼容现有代码 |
heap_4.c | 合并空闲块,减少碎片 | 较好 | 长期运行的复杂系统 |
heap_5.c | 支持多块非连续内存区域 | 最好 | 扩展内存或外部RAM |
2. STM32通知寄存器有哪些?
2.1 核心寄存器组(Cortex-M)
寄存器 | 别名 | 位宽 | 功能说明 |
---|---|---|---|
R0-R12 | 通用寄存器 | 32位 | 用于数据操作和临时存储,R0-R7 为低寄存器(所有指令可用),R8-R12 为高寄存器 |
R13 | SP (Stack Pointer) | 32位 | 栈指针: • MSP (主栈指针,特权模式默认) • PSP (进程栈指针,用户模式) |
R14 | LR (Link Register) | 32位 | 链接寄存器:存储函数/异常返回地址 |
R15 | PC (Program Counter) | 32位 | 程序计数器:指向 下一条待执行指令 的地址(当前指令地址 + 4 字节偏移) |
2.2 特殊功能寄存器(需专用指令访问)
寄存器 | 功能 |
---|---|
xPSR | 组合程序状态寄存器: • APSR (运算标志位) • IPSR (异常编号) • EPSR (执行状态) |
PRIMASK | 中断屏蔽寄存器:置1时禁止所有可屏蔽中断(NMI和HardFault除外) |
FAULTMASK | 故障屏蔽寄存器:置1时仅允许NMI中断 |
BASEPRI | 优先级屏蔽寄存器:屏蔽低于指定优先级的中断 |
CONTROL | 控制寄存器: • 选择栈指针(MSP/PSP) • 特权模式切换 |
3. 什么是优先级翻转?
我们知道任务的优先级在创建的时候就已经是设置好的,高优先级的任务可以打断低优先级的任务,抢占 CPU 的使用权。但是在很多场合中,某些资源只有一个,当低优先级任务正在占用该资源的时候,即便高优先级任务也只能乖乖的等待低优先级任务使用完该资源后释放资源。这里高优先级任务无法运行而低优先级任务可以运行的现象称为“优先级翻转”。
没理解的话,我们附张图对图进行理解,下面是优先级翻转的图解:
① L 任务正在使用某临界资源, H 任务被唤醒,执行 H 任务。但 L 任务并未执行完毕,此时临界资源还未释放。
② 这个时刻 H 任务也要对该临界资源进行访问,但 L 任务还未释放资源, 由于保护机制,H 任务进入阻塞态,L任务得以继续运行,此时已经发生了优先级翻转现象。
③ 某个时刻 M 任务被唤醒,由于 M 任务的优先级高于 L 任务, M 任务抢占了 CPU 的使用权,M任务开始运行,此时 L 任务尚未执行完,临界资源还没被释放。
④ M 任务运行结束,归还 CPU 使用权,L 任务继续运行。
⑤ L 任务运行结束,释放临界资源,H 任务得以对资源进行访问,H 任务开始运行。
4. 什么是优先级继承?
在 H 任务申请该资源的时候,由于申请不到资源会进入阻塞态,那么系统就会把当前正在使用资源的 L 任务的优先级临时提高到与 H 任务优先级相同,此时 M 任务被唤醒了,因为它的优先级比 H 任务低,所以无法打断 L 任务,因为此时 L 任务的优先级被临时提升到 H,所以当 L 任务使用完该资源了,进行释放,那么此时 H 任务优先级最高,将接着抢占 CPU 的使用权, H 任务的阻塞时间仅仅是 L 任务的执行时间,此时的优先级的危害降到了最低:
① L 任务正在使用某临界资源, H 任务被唤醒,执行 H 任务。但 L 任务并未执行完毕,此时临界资源还未释放。
② 这个时刻 H 任务也要对该临界资源进行访问,但 L 任务还未释放资源, 由于保护机制,H 任务进入阻塞态,此时由于优先级继承机制,将 L 任务的优先级拉倒和 H 任务的优先级一样。
③ 某个时刻 M 任务被唤醒,虽然 M 优先级比最初的 L 任务的优先级高,但是,此时 L 的优先级被拉到和 H 任务的优先级一样,所以 M 处于就绪态。
④ L 任务运行结束,释放临界资源,L 任务的优先级回到最初的状态。
⑤ 此时任务 H 和 M均处于就绪态,但是 H 的优先级比 M 的高,且 L 任务已经运行结束,释放临界资源,因此 H 任务得以对资源进行访问,H 任务开始运行。
⑥ M 任务比 L 任务的优先级高,M 任务执行。
千题千解·嵌入式工程师八股文详解_时光の尘的博客-CSDN博客