FreeRTOS再学习——2nd——信号量和优先级反转问题

摘要:
在第三步之后,二进制信号量变为无效,因此任务将再次进入阻塞状态,就像第一步一样,直到中断再次发生,并调用函数xSemaphoreGiveFromISR0释放信号量。优先级反转问题:目前,任务有三个优先级:1、2和3。

信号量:

信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。
不同的信号量其应用场景不同,但有些应用场景是可以互换着使用的。

二值信号量只有0和1,表示信号量的两个状态,适用于立flag
信号量的另一个重要的应用场合就是任务同步,用于任务与任务或中断与任务之间的同步。裸机编写中断服务函数的时候一般都只是在中断服务函数中打个标记,然后在其他的地方根据标记来做具体的处理过程。在使用RTOS系统的时候我们就可以借助信号量完成此功能,当中断发生的时候就释放信号量,中断服务函数不做具体的处理。具体的处理过程做成一个任务,这个任务会获取信号量,如果获取到信号量就说明中断发生了,那么就开始完成相应的处理,这样做的好处就是中断执行时间很短
二值信号量,用来处理当某个事件产生后,标志某位,让某个任务进入运行态
还是上图容易理解:(大用途)
在这里插入图片描述
由于任务函数一般都是一个大循环,所以在任务做完相关的处理以后就会再次调用函数xSemaphoreTake()获取信号量。在执行完第三步以后二值信号量就已经变为无效的了,所以任务将再次进入阻塞态,和第一步一样, 直至中断再次发生并且调用函数xSemaphoreGiveFromISR0释放信号量。
创建二值信号量API:

在这里插入图片描述
释放信号量API:
在这里插入图片描述
获取信号量API:
在这里插入图片描述
使用总结:
当一个事件发生,释放信号量,也即flag=1,有一个任务在获取信号量,也就是一直在while(1),1就是信号量是否有效的标志;当事件未产生时,任务不执行,也就是在阻塞态,当中断或者其他任务释放信号量,指定任务获取到信号量,开始执行,也就是从阻塞态就如就绪态等待CPU的使用权(因为有可能有别的优先级更高的任务在执行,如果此时它的优先级最高那就是进入运行态),相比裸机:裸机轮询实时性更差点(我觉得)

计数型信号量:包括信号量和信号量值
适用于这种情况:相比二值信号量的立flag,这货可以记录立flag的次数,比如说停车场停车,停一辆车立一个flag,二值信号量只能说明有车停进来了,这货可以记录停进来几辆车。
这货是倒着计数的额,从信号量值开始倒着计数,当为0时,说明木得资源了
创建计数型信号量API:
在这里插入图片描述
信号量的获取和释放和二值信号量一样。

优先级反转问题:
当前有三个任务的优先分别问1、2、3。
开始的时候,1和2在挂起状态等待某一事件发生,优先级最低的3正在运行,当优先级最高的1的事件发生后,他开始运行,3先停下来,但是它访问某一共享资源时,发现3之前在用,并且3使用的这一共享资源的信号量还被3占用着,1只能等着3用完这个共享资源,CPU使用权暂时3用着,此时2的事件发生了,那么CPU使用权给2,2要做的事不用3所用的共享资源,所以2就先执行完了,然后CPU使用权给3,当3使用完和1相同的共享资源后,1开始执行,3等着,然后1执行完,3再执行。
此时,优先级为2的任务却先在任务优先级更高的1任务执行完之前执行完了,1和2个优先级就反转了。这是我的理解,看图看图
在这里插入图片描述

解决优先级反转之互斥信号量:(不能在中断服务函数中使用)
互斥访问中互斥信号量相当于一个钥匙,当任务想要使用资源的时候就必须先获得这个钥匙,当使用完资源以后就必须归还这个钥匙,这样其他的任务就可以拿着这个钥匙去使用资源。也就是说,只能访问一次,访问完,需要释放

互斥信号量解决优先级反转的问题的方法:

在这里插入图片描述
也就是说,任务1在等任务3使用那个共享资源的时候,把任务3的优先级变成1,等它使用完了再把它的优先级变回去,也就是说,2不能在1等待3执行访问和1的共享资源的的时候先执行了,只是把影响降到最低,最后还是得等3先用完共享的资源。

创建互斥信号量API:
在这里插入图片描述

递归互斥信号量
可以看作是一个特殊的互斥信号量,已经获取了互斥信号量的任务就不能再次获取这个互斥信号量,但是递归互斥信号量不同,已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量,而且次数不限!一个任务使用函数xSemaphore’ TakeRecursive()成功的获取了多少次递归互斥信号量就得使用函数xSemaphoreGiveRecursive(释放多少次!比如某个任务成功的获取了5次递归信号量,那么这个任务也得同样的释放5次递归信号量。
递归互斥信号量也有优先级继承的机制,所以当任务使用完递归互斥信号量以后一定要记得释放。同互斥信号量一样,递归互斥信号量不能用在中断服务函数中。
创建递归信号量API:
在这里插入图片描述

免责声明:文章转载自《FreeRTOS再学习——2nd——信号量和优先级反转问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇从NSGA到 NSGA II[django]l利用xlrd实现xls文件导入数据下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux 进程管理 ps、top、pstree命令

ps命令:查看系统中正在运行的进程 ps 是用来静态地查看系统中正在运行的进程的命令。不过这个命令有些特殊,它的部分选项不能加入"-",比如命令"ps aux",其中"aux"是选项,但是这个选项不能加入"-"。这是因为 ps 命令的部分选项需要遵守 BSD 操作系统的格式。所以,ps 命令的常用选项的组合是固定的。ps 命令格式如下: 查看系统中所有的进...

Oracle 递归拼接字段

效果 sql SELECT LISTAGG(T.NAME, '/ ') WITHIN GROUP(ORDER BY LEVEL DESC) ASRESULT FROMS_WORK_RESOURSE T START WITH T.WORK_RESOURCE_NO = 323CONNECT BY PRIOR T.PARENT_WORK_RESOURCE...

Android O : DNS列表获取及IPv4/IPv6优先级修改

一、Android应用获取有线网络DNS列表 /** * 获取DNS列表 */ private List<String> getDnsList() { List<String> dnsList = new ArrayList(); if (this.mIEthern...

unity行为树简介

目前在Unity3D游戏中一般复杂的AI都可以看到行为树的身影,简单的AI使用状态机来实现就可以了,所以这里我也是简单的学习下,为以后用到做准备。 行为树的概念出现已经很多年了,总的来说,就是使用各种经典的控制节点+行为节点进行组合,从而实现复杂的AI。 Behavior Designer插件里,主要有四种概念节点,都称之为Task。包括: (1)Comp...

C#多线程(一)

一、基本概念 1、进程 首先打开任务管理器,查看当前运行的进程: 从任务管理器里面可以看到当前所有正在运行的进程。那么究竟什么是进程呢? 进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程...

MySQL-锁

1. 公平锁与非公平锁   公平锁:严格按照线程启动的顺序执行,不允许其他线程插队执行;非公平锁允许插队;   当使用非公平锁时,会立刻尝试配置状态,成功则:插队执行,失败则:与公平锁一样调用acquire()方法,以排他方式获取锁,成功后立刻返回,否则将线程加入队列,直到成功调用为止。 2. 悲观锁与乐观锁   两种常见的资源并发锁设计。   悲观锁:先...