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

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)应用任务的优先级比初始任务低时

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

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS提供了多种方法来保护临界资源,其中最常用的是使用任务间通信机制中的二值信号量(Binary Semaphore)或互斥量(Mutex)。这两种机制都可以用来保护临界资源,防止多个任务同时访问临界资源导致数据不一致或错误。 使用二值信号量时,可以将信号量的初始值设置为1,表示临界资源未被占用。当一个任务需要访问临界资源时,首先获取信号量,如果信号量的值为1,则表示临界资源未被占用,该任务可以访问临界资源;如果信号量的值为0,则表示临界资源已被占用,该任务需要等待直到信号量的值变为1才能访问临界资源。当任务访问临界资源后,需要释放信号量,将其值设置为1,表示临界资源已经被释放。 使用互斥量时,可以将互斥量的初始值设置为1,表示临界资源未被占用。当一个任务需要访问临界资源时,首先获取互斥量,如果互斥量的值为1,则表示临界资源未被占用,该任务可以访问临界资源;如果互斥量的值为0,则表示临界资源已被占用,该任务需要等待直到互斥量的值变为1才能访问临界资源。当任务访问临界资源后,需要释放互斥量,将其值设置为1,表示临界资源已经被释放。 需要注意的是,使用二值信号量或互斥量保护临界资源时,需要保证所有访问临界资源的任务都使用同一个信号量或互斥量对象进行保护,否则会出现数据不一致或错误的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值