RTOS共享资源保护

UCOS共享资源保护

在UCOSIII中对于共享资源访问的方式有以下几种:

  • 关中断的方式
  • 禁止任务调度
  • 信号量的使用
  • 互斥信号量的使用

通过下面的表格的分析,我们可以知道他们的使用场景和一些细微的差别

资源共享的方法使用场景
关中断、开中断方式前提条件:当访问共享资源的速度很快(读取或者写入极少变量时:如喂狗操作、FLASH写数据、需要和中断服务程序共享变量或者数据结构等等)以至于访问共享资源所花的时间小于UCOSIII的中断关闭时间。影响:由于使用该方式会影响中断延迟,所以极度不推荐使用该方法。
调度器上锁、解锁前提条件:当访问共享资源的时间比UCOSIII的中断关闭时间长,但是其比UCOSIII给调度器上锁时间短时,如变量值自加。影响:给调度器上锁会导致调度器上锁的任务成为最高优先级。这已经有点反UCOSIII的初衷,所以同样不推荐该方法,当然改方法要比关中断要好一些,起码不会影响系统的中断
信号量前提条件:当所有的任务可以无限等待对共享资源的访问时。影响:使用信号量可能会导致优先级反转,这样会破坏任务的预期执行的顺序,但是在速度上比互斥锁要快
互斥型信号量(互斥锁)前提条件:这是共享资源访问的首选方式,特别是当某些任务对共享资源访问有时间要求的时候。影响:UCOSIII的互斥锁具有一整套内置的优先级继承机制,用来避免优先级反转的问题,与信号量相比速度会慢一些。

下面我们将对信号量和互斥锁这两种常用的方式进行深入的分析。

信号量:

信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。
信号量分为2种:二进制信号量与计数型信号量,二进制信号量只能取0和1两个值,计数型信号量不止可以取2个值,在共享资源中只有任务可以使用信号量,中断服务程序则不能使用。

二进制信号量:

某一资源对应的信号量为1的时候,那么就可以使用这一资源,如果对应资源的信号量为0,那么等待该信号量的任务就会被放进等待信号量的任务表中。在等待信号量的时候也可以设置超时,如果超过设定的时间任务没有等到信号量的话那么该任务就会进入就绪态。任务以“发信号”的方式操作信号量。可以看出如果一个信号量为二进制信号量的话,一次只能一个任务使用共享资源。

计数型信号量:

有时候我们需要可以同时有多个任务访问共享资源,这个时候二进制信号量就不能使用了,计数型信号量就是用来解决这个问题的。比如某一个信号量初始化值为10,那么只有前10个请求该信号量的任务可以使用共享资源,以后的任务需要等待前10个任务释放掉信号量。每当有任务请求信号量的时候,信号量的值就会减1,直到减到为0.当有任务释放掉信号量的时候信号量的值就会加1

信号量API函数

信号量的创建:

要想使用信号量,肯定需要先创建一个信号量,我们使用函数OSSemCreate()来创建信号量,函数原型如下:

在这里插入图片描述

1.p_sem: 指向信号量控制块,我们需要按照如下所示方式定义一个全局信号量,并将这个信号量的指针传递给函数OSSemCreate()。 OS_SEM TestSem;

2.p_name: 指向信号量的名字。

3.cnt: 设置信号量的初始值,如果此值为1,代表此信号量为二进制信号量,如果大于1的话就代表此信号量为计数型信号量。

4.p_err: 保存调用此函数后的返回的错误码。

信号量的请求:

当一个任务需要独占式的访问某个特定的系统资源时,需要与其他任务或中断服务程序同步,或者需要等待某个事件的发生,应该调用函数OSSemPend(),函数原型如下:

信号量创建的结构体

  1. p_sem: 指向一个信号量的指针
  2. timeout: 指定等待信号量的超时时间(时钟节拍数),如果在指定时间内没有等到信号量则允许任务恢复执行。如果指定时间为0的话,任务就会一直等待下去,直到等到信号量。
  3. opt: 用于设置是否使用阻塞模式,有下面2个选项。OS_OPT_PEND_BLOCKING 指定信号量无效时,任务挂起以等待信号量。OS_OPT_PEND_NON_BLOCKING 信号量无效时,任务直接返回
  4. p_ts: 指向一个时间戳,用来记录接收到信号量的时刻,如果这个参数赋值NULL,则说明用户没有要求时间戳。
  5. p_err: 保存调用本函数后返回的错误码
信号量的释放(也叫信号量的发送):

任务获得信号量以后就可以访问共享资源了,在任务访问完共享资源以后必须释放信号量,释放信号量也叫发送信号量,使用函数OSSemPost()发送信号量。如果没有任务在等待该信号量的话则OSSemPost()函数只是简单的将信号量加1,然后返回到调用该函数的任务中继续运行。如果有一个或多个任务在等待这个信号量,则优先级最高的任务获得这个信号量,然后由调度器来判定刚获得信号量的任务是否为系统中优先级最高的就绪任务,如果是,则系统将进行任务切换,运行这个就绪任务,OSSemPost()函数原型如下:

在这里插入图片描述

  1. p_sem: 指向一个信号量的指针。
  2. opt: 用来选择信号量发送的方式。
    OS_OPT_POST_1 仅向等待该信号量的优先级最高的任务发送信号量。
    OS_OPT_POST_ALL 向等待该信号量的所有任务发送信号量。
    OS_OPT_POST_NO_SCHED 该选项禁止在本函数内执行任务调度操作。即使该函数使得更高优先级的任务结束挂起进入就绪状态,也不会执行任务调度,而是会在其他后续函数中完成任务调度。
  3. p_err: 用来保存调用此函数后返回的错误码。
使用信号量访问共享资源:

在这里插入图片描述
在这里插入图片描述

使用信号量导致优先级反转:

优先级反转在可剥夺内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能会导致严重的后果,下图就是一个优先级反转的例子。

在这里插入图片描述

  1. 任务H和任务M处于挂起状态,等待某一事件的发生,任务L正在运行。
  2. 某一时刻任务L想要访问共享资源,在此之前它必须先获得对应该资源的信号量。
  3. 任务L获得信号量并开始使用该共享资源。
  4. 由于任务H优先级高,它等待的事件发生后便剥夺了任务L的CPU使用权。
  5. 任务H开始运行。
  6. 任务H运行过程中也要使用任务L正在使用着的资源,由于该资源的信号量还被任务L占用着,任务H只能进入挂起状态,等待任务L释放该信号量。
  7. 任务L继续运行。
  8. 由于任务M的优先级高于任务L,当任务M等待的事件发生后,任务M剥夺了任务L的CPU使用权。
  9. 任务M处理该处理的事情
  10. 任务M执行完毕后,将CPU使用权归还给任务L
  11. 最终任务L完成所有的工作并释放了信号量,到此为止,由于实时内核知道有个高优先级的任务在等待这个信号量,故内核做任务切换
  12. 任务H得到该信号量并接着运行。

互斥锁:

为了避免优先级反转这个问题,UCOSIII支持一种特殊的二进制信号量:互斥信号量,用它可以解决优先级反转问题,如下图:

在这里插入图片描述

  1. 任务H与任务M处于挂起状态,等待某一事件的发生,任务L正在运行中
  2. 某一时刻任务L想要访问共享资源,在此之前它必须先获得对应资源的互斥型信号量。
  3. 任务L获得互斥型信号量并开始使用该共享资源。
  4. 由于任务H优先级高,它等待的事件发生后便剥夺了任务L的CPU使用权。
  5. 任务H开始运行。
  6. 任务H运行过程中也要使用任务L正在使用的资源,考虑到任务L正在占用着资源,UCOSIII会将任务L的优先级升至同任务H一样,使得任务L能继续执行而不被其他中等优先级的任务打断。
  7. 任务L以任务H的优先级继续运行,注意此时任务H并没有运行,因为任务H在等待任务L释放掉互斥信号量。
  8. 任务L完成所有的任务,并释放掉互斥型信号量,UCOSIII会自动将任务L的优先级恢复到提升之前的值,然后UCOSIII会将互斥型信号量给正在等待着的任务H。
  9. 任务H获得互斥信号量开始运行。
  10. 任务H不再需要访问共享资源,于是释放掉互斥型信号量。
  11. 由于没有更高优先级的任务需要执行,所以任务H继续执行。
  12. 任务H完成所有工作,并等待某一事件发生,此时UCOSIII开始运行在任务H或者任务L运行过程中已经就绪的任务M。
  13. 任务M继续执行

注意:只有任务才能使用互斥信号量(中断服务程序则不可以),UCOSIII运行用户嵌套使用互斥型信号量,一旦一个任务获得了一个互斥型信号量,则该任务最多可以对该互斥型信号量嵌套使用250次,当然该任务只有释放相同的次数才能真正释放这个互斥信号量。
与普通信号量一样,对于互斥信号量也可以进行许多操作,如下图,文件os_mutex.c是关于互斥信号量的。

互斥锁函数API:

互斥锁函数API接口

互斥锁的创建:

创建互斥信号量使用函数OSMutexCreate()函数,函数原型如下:
在这里插入图片描述

  1. p_mutex: 指向互斥型信号量控制块。互斥型信号量必须由用户应用程序进行实际分配,可以使用如下代码。 OS_MUTEX MyMutex;
  2. p_name:互斥信号量的名字。
  3. p_err: 调用此函数后返回的错误码
互斥锁的请求:

使用函数OSMutexPend()

在这里插入图片描述

  1. p_mutex: 指向互斥信号量。

  2. timeout: 指定等待互斥信号量的超时时间(时钟节拍数),如果在指定的时间内互斥信号量没有释放,则允许任务恢复执行。该值设置为0的话,表示任务将会一直等待下去,直到信号量被释放掉。

  3. opt: 用于选择是否使用阻塞模式。
    OS_OPT_PEND_BLOCKING 指定互斥信号量被占用时,任务挂起等待该互斥信号量。
    OS_OPT_PEND_NON_BLOCKING 指定当互斥信号量被占用时,直接返回任务。
    注意!当设置OS_OPT_PEND_NON_BLOCKING时,timeout参数就没有意义了,应设置为0

  4. p_ts: 指向一个时间戳,记录发送、终止或删除互斥信号量的时刻。

  5. p_err: 用于保存调用此函数后返回的错误码。

互斥锁的释放:

调用函数OSMutexPost()函数来释放互斥型信号量。

在这里插入图片描述

  1. p_mutex: 指向互斥信号量。

  2. opt: 用来指定是否进行任务调度操作
    OS_OPT_POST_NONE 不指定特定的选项
    OS_OPT_POST_NO_SCHED 禁止在本函数内执行任务调度操作

  3. p_err: 用于保存调用此函数后返回的错误码。

    互斥锁实战训练:

    在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
共享资源FreeRTOS是指多个任务之间共享的数据或硬件资源,例如全局变量、外设等。共享资源的并发访问可能导致数据的不一致性,为了解决这个问题,FreeRTOS提供了一些同步机制,包括临界区、互斥锁和递归互斥锁。在FreeRTOS,临界区可以通过调用任务管理器API函数来实现。递归互斥锁是一种特殊的互斥锁,允许同一个任务多次获取该锁,而不会导致死锁。通过合理设置共享资源保护时长,可以平衡任务对共享资源的需求和保护的程度。较小的保护时长意味着应尽快使用共享资源并退出保护,较大的保护时长则允许更长时间的使用共享资源。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [RTOS共享资源保护-任务间共享资源保护总结及再议死锁](https://blog.csdn.net/wangyx1234/article/details/128129054)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [FreeRTOS学习-共享资源的同步访问](https://blog.csdn.net/o0onlylove0o/article/details/129678247)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值