临界段介绍

发布时间:2026/7/28 14:21:54
临界段介绍 一、什么是临界段1临界段Critical Section也叫临界区是指一段在执行过程中不能被中断的代码段。在多线程多任务环境中多个线程可能同时访问同一块共享资源如全局变量、硬件外设、通信缓冲区等如果不加以保护就会导致数据竞争和不一致性问题。2一个形象的比喻全局变量就像一个“枪靶子”谁都可以向它“开枪”读写操作。但当我开枪时你不能同时开枪否则就不知道是谁命中了靶子。二、临界段为何会被打断临界段面临的打断风险主要有两类打断来源说明系统调度任务切换RTOS的调度器可能在任意时刻挂起当前线程切换到另一个线程执行外部中断硬件中断触发时CPU会暂停当前代码去执行中断服务函数ISR值得注意的是在RT-Thread等RTOS中系统调度最终也是通过PendSV中断来实现线程切换的。因此归根结底对临界段的威胁都可以归结为中断。三、临界段的保护方法3.1 方法概览在嵌入式系统中保护临界段主要有以下几种手段保护方法核心原理适用场景关中断禁用所有或部分中断保证代码原子执行保护任务与中断共享的资源或需严格时序的代码禁用任务调度调度器锁禁止任务切换但中断仍可响应仅保护任务与任务之间共享的资源互斥量Mutex通过加锁/解锁机制实现互斥访问保护较复杂的临界资源支持阻塞等待原子操作利用硬件支持的原子指令保护简单的变量操作如自增、自减3.2 关中断——最底层的保护手段关中断是保护临界段的最核心、最彻底的手段。它的原理简单直接进入临界段前关闭中断退出临界段时再打开中断。在Cortex-M内核中为了快速开关中断专门提供了 CPS指令CPSID I ; PRIMASK1关中断 CPSIE I ; PRIMASK0开中断 CPSID F ; FAULTMASK1关异常 CPSIE F ; FAULTMASK0开异常Cortex-M内核中有三个中断屏蔽寄存器它们的屏蔽力度不同寄存器位宽功能PRIMASK1位置1后屏蔽所有可屏蔽中断仅NMI和硬Fault可响应FAULTMASK1位置1后仅NMI可响应连硬Fault都被屏蔽BASEPRI最多9位设置优先级阈值屏蔽优先级大于等于该值的所有中断设置优先级阈值屏蔽优先级大于等于该值的所有中断四、T-Thread中的临界段保护APIRT-Thread提供了两种不同粒度的临界段保护接口开发者需要根据共享资源的访问方来选择。4.1 关中断级保护rt_hw_interrupt_disable/enable适用场景临界资源会被任务和中断服务函数ISR共同访问时。rt_base_tlevel;levelrt_hw_interrupt_disable();/* 关闭全局中断保存当前中断状态 *//* 临界段开始 *//* 操作被任务和中断共享的资源 *//* 临界段结束 */rt_hw_interrupt_enable(level);/* 恢复之前的中断状态 */底层实现原理以Cortex-M为例关中断函数 rt_hw_interrupt_disable() 的核心汇编代码rt_hw_interrupt_disable PROC MRS r0, PRIMASK ; ① 读取当前PRIMASK值到r0作为返回值 CPSID I ; ② 关闭中断PRIMASK置1 BX LR ; ③ 返回 ENDP开中断函数 rt_hw_interrupt_enable(level) 的核心汇编代码rt_hw_interrupt_enable PROC MSR PRIMASK, r0 ; 将传入的level值写回PRIMASK BX LR ENDP为什么关中断前要保存PRIMASK值 ——为了支持嵌套调用。如果在关中断之前中断已经是关闭状态例如外层已经调用了关中断那么退出时就不能简单执行 CPSIE I 打开中断而应该恢复到进入前的状态。保存并恢复PRIMASK值可以正确支持嵌套场景。4.2 调度器锁保护rt_enter/exit_critical适用场景临界资源仅在任务线程之间共享不涉及中断访问时。rt_enter_critical();/* 禁止任务调度 *//* 临界段开始 *//* 操作仅在线程间共享的资源 *//* 临界段结束 */rt_exit_critical();/* 恢复任务调度 */注意调度器锁只禁止了任务切换并未关闭任何中断中断仍然可以正常响应。因此如果中断服务函数也会访问该资源使用调度器锁是无效的。rt_enter_critical() 和 rt_exit_critical() 同样支持嵌套调用内部使用一个计数器来管理锁的深度。五、两种保护方式的对比与选择对比维度关中断 (rt_hw_interrupt_disable)调度器锁 (rt_enter_critical)是否关闭中断关闭全局中断不关闭中断是否禁止任务切换间接禁止中断被关PendSV无法触发直接禁止调度中断响应中断被延迟中断可正常响应影响系统实时性影响较大影响较小适用场景任务与中断共享资源仅任务间共享资源使用建议临界段代码必须极短临界段代码可稍长选择原则1如果共享资源的访问方包括中断服务函数 → 必须使用 rt_hw_interrupt_disable()关中断2如果共享资源仅在任务之间访问 → 优先使用 rt_enter_critical()调度器锁对系统实时性影响更小六、使用临界段的黄金法则法则一临界段代码必须极短关中断会直接影响系统的中断响应延迟。如果临界段执行时间过长可能导致1系统时钟节拍SysTick丢失2串口数据溢出3硬件时序错过关键窗口4关中断时间是实时内核最重要的指标之一它直接影响系统对实时事件的响应能力。法则二严禁在临界段内调用阻塞函数在临界段内绝对禁止调用任何可能导致线程挂起阻塞的函数例如1rt_thread_delay() / rt_thread_sleep()2rt_sem_take() / rt_mutex_take() / rt_mb_recv() 等3任何可能引发调度或等待的操作如果调度被锁或中断被关系统将永远无法切换出去程序会直接卡死。法则三必须成对使用disable 和 enable、enter 和 exit 必须成对出现。如果只上锁不解锁会导致系统永远无法响应中断或进行任务调度造成灾难性后果。建议的编码模式rt_base_tlevelrt_hw_interrupt_disable();/* 临界段代码——越短越好 */rt_hw_interrupt_enable(level);法则四区分场景避免滥用不要因为方便就随意使用 rt_hw_interrupt_disable()关全局中断。如果只是任务间共享资源优先使用调度器锁以最小化对系统实时性的影响。七、其他同步机制简介除了上述两种“粗暴”的关中断/关调度方式RT-Thread还提供了更精细的同步机制机制特点适用场景互斥量Mutex支持优先级继承可递归锁定支持超时等待保护较复杂的临界资源允许线程阻塞等待信号量Semaphore轻量级同步可用于资源计数控制对有限资源的访问或用作事件通知事件Event支持多事件组合触发线程间的事件同步互斥量等机制虽然功能更丰富但开销也更大。对于极短的关键操作如修改一个全局变量关中断仍然是最快、最直接的方式。八、总结要点说明定义临界段是一段执行时不能被中断的代码段威胁来源任务切换调度和外部中断核心保护手段关中断rt_hw_interrupt_disable和调度器锁rt_enter_critical选择原则涉及中断用关中断仅任务间用调度器锁关键约束代码极短、不阻塞、成对使用、避免滥用临界段保护是多任务实时系统中保障数据一致性和系统正确性的基石。理解并正确使用临界段是编写稳定可靠嵌入式应用程序的基本功。