十、什么是临界资源及如何访问临界资源

1、什么是临界资源?

临界资源是一次仅允许一个进程使用的共享资源。通俗可以理解为同一时刻只能由一个进程进行访问的资源。

2、什么是临界区?

每个进程中访问临界资源的那段代码称为临界区(Critical Section)。即是一段不能被打断的代码段
即保护了关键代码的执行不被打断,但也会影响系统的实时,任何使用了操作系统的中断响应都不会比裸机快。
每次只准许一个进程进入临界区,进入后不允许其他进程进入。

3、临界资源访问的两种方法

FreeRTOS中提供读写队列等API函数内部,均进行了临界资源的访问(即不会被其他事情干扰),在任务中如果不想使用队列等并且也不想被其他事情打扰均可参考这种进入临界区的做法。

(1)关闭中断:避免了其他任务和中断来破坏,即这时候中断和任务调度无法正常进行

在FreeRTOS提供的读写队列、信号量、互斥量等API函数里面,均实现了临界区的访问,其采用的均是关闭中断的方法来进行临界区的访问。
那么问题来了——这个关闭中断是关闭了所有中断吗?
答案很显然,肯定不是了,它关闭的只是部分优先级较低的中断。FreeRTOS为什么这样操作和在代码上如何做的在后面中断管理的博客中会详细说说。

进行临界资源访问的时候,这些API函数都是成对出现的,即有进入临界区的API函数,也有退出的。具体如下

1)在任务中屏蔽中断

/* 在任务中,当前时刻中断是使能的
* 执行这句代码后,屏蔽中断
*/
taskENTER_CRITICAL();
/* 访问临界资源 */
/* 重新使能中断 */
taskEXIT_CRITICAL();

2)在中断服务函数中屏蔽中断

{
 /* 用来记录当前中断是否使能 */
 UBaseType_t uxSavedInterruptStatus;
 
 /* 在 ISR 中,当前时刻中断可能是使能的,也可能是禁止的
 * 所以要记录当前状态, 后面要恢复为原先的状态
 * 执行这句代码后,屏蔽中断
 */
 uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
 
 /* 访问临界资源 */
 /* 恢复中断状态 */
 taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
 /* 现在,当前 ISR 可以被更高优先级的中断打断了 */
}

3)补充说明

taskENTER_CRITICA()/taskEXIT_CRITICAL()之间和taskENTER_CRITICA_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()之间:
a)低优先级的中断被屏蔽了:即优先级低于、等于configMAX_SYSCALL_INTERRUPT_PRIORITY
b)高优先级的中断可以产生:优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY

4)为什么关闭中断也使任务调度停止了?——因为任务调度依赖于systick中断

(2)关闭调度器:避免了其他任务破坏,但这时候中断还是可以发生和处理的

在事件组的相关API函数内部进入临界区的方法均是采用关闭调度器的方法

/* 暂停调度器 */
void vTaskSuspendAll( void );
/* 恢复调度器
* 返回值: pdTRUE 表示在暂定期间有更高优先级的任务就绪了
* 可以不理会这个返回值
*/
BaseType_t xTaskResumeAll( void );

4、如果没有使用临界区后果会如何?

(1)应用任务的优先级比初始任务高时

创建完应用任务后会立马去执行优先级最高的任务,当其被阻塞时回到初始任务继续创建任务,直至应用任务创建完成,最后把自己(初始任务)删除。

(2)应用任务的优先级和初始任务一样时

创建完应用任务后根据任务的时间片来执行,直到所有应用任务创建完成,最后初始任务把自己删除。

(3)应用任务的优先级比初始任务低时

创建完应用任务后不会被执行,除非优先级和上述两种情况一样,直到所有应用任务创建完成,最后初始任务把自己删除。

<think>我们正在讨论临界资源的概念。根据用户要求,需要参考站内引用并整合到回答中。用户之前的问题是关于临界区的,现在转向临界资源,所以需要明确区分这两个概念。首先,临界资源的定义:-引用[1]明确指出临界资源是“一次仅允许一个进程使用的共享资源”,如打印机、磁带机等硬件设备,或共享变量、文件等软件资源。-引用[4]中示例的临界资源是一个共享存储区的栈(用于块号分配)。关键特征:1.**互斥访问**:引用[2]强调资源不能被多个线程共享,只能被一个线程在任一时刻使用(互斥条件)。2.**共享性**:多个进程/线程需要共同使用的资源。3.**竞争性**:未受保护的访问会导致竞态(引用[2])。示例:-**硬件示例**:打印机(若多个进程同时发送打印任务,输出会混乱)。-**软件示例**:-引用[4]的共享栈(存储块号)。-引用[1]的Python示例中的共享变量`ticket`。未保护临界资源的后果:-引用[1]和[4]均演示了竞态问题:多个线程同时修改`ticket`导致负值;共享栈的块号分配/释放混乱。保护机制:-通过临界区实现保护(引用[1][3]):-使用互斥锁(如Python的`threading.Lock`)或信号量(引用[3]的P/V操作)确保原子访问。总结表格:|**特性**|**临界资源**|**临界区**||----------------|------------------------------------------|-------------------------------||本质|共享实体(硬件/软件)|访问临界资源的代码段||保护目标|资源本身|资源访问过程||未保护后果|数据不一致、系统错误(如`ticket`为负)|同左||保护方式|间接通过临界区实现|直接使用互斥锁/信号量|相关问题:1.临界资源与临界区的区别是什么?2.如何识别程序中的临界资源?3.信号量如何保护临界资源?[^3]</think>### 临界资源的定义与核心特性 **临界资源(Critical Resource)** 指在多线程/多进程环境中**必须互斥访问的共享资源**。其核心定义为: > **一次仅允许一个执行流(线程或进程)访问的共享实体**,未受保护的并发访问会导致数据不一致或系统错误[^1][^2]。 #### 关键特性 1. **互斥性** - 任一时刻仅允许一个执行流访问资源(如引用[2]所述互斥条件)[^2]。 2. **共享性** - 资源被多个执行流共同使用(如全局变量、硬件设备)。 3. **竞争性** - 未保护时,并发访问引发**竞态条件(Race Condition)**(引用[2]的“竞态”概念)[^2]。 --- ### 临界资源的类型与示例 #### 常见类型 | **类型** | **示例** | **风险场景** | |----------------|----------------------------------|-----------------------------| | **硬件资源** | 打印机、磁盘驱动器 | 多进程同时写入导致输出混乱 | | **软件资源** | 共享内存、数据库表、全局变量 | 并发修改引发数据逻辑错误 | | **系统资源** | 文件描述符、网络端口 | 资源耗尽或访问冲突 | #### 经典示例解析 1. **共享变量(软件资源)** - **场景**:多线程售票系统,共享变量 `ticket` 表示余票数[^1]。 - **风险**: ```python # 未保护的代码 if ticket > 0: # 线程A和B同时通过检查 ticket -= 1 # 导致ticket被重复减少 ``` - 结果:`ticket` 可能变为负数(违反业务逻辑)[^1][^4]。 2. **共享存储区栈(系统资源)** - **场景**:Linux进程通过共享栈分配块号(引用[4]示例)[^4]。 - 服务进程初始化栈:栈顶为1, 栈底为n(空闲块号)。 - 客户进程调用 `getblock()` 弹出块号(分配)。 - **风险**: - 多进程同时弹出导致分配重复块号。 - 多进程同时压入导致栈状态不一致。 --- ### 临界资源的保护机制 需通过**同步互斥机制**控制访问: 1. **互斥锁(Mutex)** - 访问前加锁,访问后解锁,确保原子性[^1][^3]。 ```python lock = threading.Lock() lock.acquire() # 进入临界区前加锁 if ticket > 0: ticket -= 1 # 临界资源访问 lock.release() # 退出临界区解锁 ``` 2. **信号量(Semaphore)** - 通过P/V操作控制资源数量(引用[3])[^3]: - **P操作**(原子减一):申请资源,若资源为0则阻塞。 - **V操作**(原子加一):释放资源。 ```c sem_t sem; sem_init(&sem, 0, 1); // 初始化二值信号量(1表示可用) sem_wait(&sem); // P操作 access_resource(); // 访问临界资源 sem_post(&sem); // V操作 ``` 3. **硬件级原子指令** - 如Test-and-Set指令,确保“检查-修改”操作的原子性[^4]。 --- ### 未保护临界资源的后果 1. **数据不一致** - 如售票系统的余票数错误[^1]。 2. **资源泄漏** - 如文件描述符被重复分配导致耗尽[^4]。 3. **死锁(Deadlock)** - 触发引用[2]的四个条件(互斥、持有等待、不可抢占、循环等待)[^2]。 --- ### 相关问题 1. 临界资源与临界区有何区别与联系?[^1] 2. 如何设计信号量解决生产者-消费者问题?[^3] 3. 哪些场景可能因临界资源未保护引发死锁?[^2] 4. 原子操作在保护临界资源中的作用是什么?[^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值