第14章 信号量 本章节开始讲解RTX的另一个重要的任务间的同步和资源共享机制,信号量。 本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。 14.1 信号量 14.2 信号量API函数 14.4 实验例程说明(中断方式通信) 14.5 总结
14.1 信号量
14.1.1 信号量的概念及其作用 信号量(semaphores)是20世纪60年代中期EdgserDijkstra发明的。使用信号量的最初目的是为了给共享资源建立一个标志,该标志表示该共享资源被占用情况。这样,当一个任务在访问共享资源之前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。 实际的应用中,信号量的作用又该如何体现呢?比如有个30人的电脑机房,我们就可以创建信号量的初始化值是30,表示30个可用资源,不理解的初学者表示信号量还有初始值?是的,信号量说白了就是共享资源的数量。另外我们要求一个同学使用一台电脑,这样每有一个同学使用一台电脑,那么信号量的数值就减一,直到30台电脑都被占用,此时信号量的数值就是0。如果此时还有几个同学没有电脑可以使用,那么这几个同学就得等待,直到有同学离开,有一个同学离开,那么信号量的数值就加1,有两个就加2,依次类推。刚才没有电脑用的同学此时就有电脑可以用了,有几个同学用,信号量就减几,直到再次没有电脑可以用,这么一个过程就是使用信号量来管理共享资源的过程。 平时使用信号量主要实现以下两个功能: 1. 两个任务或者中断函数跟任务之间的同步功能,这个和上章节讲解的事件标志组是类似的。其实就是共享资源为1的时候。 2. 多个共享资源的管理,就像上面举的机房上机的例子。 实际上信号量还有很多其它用法,而且极具挑战性,可以大大的开拓大家的视野,有兴趣的同学可以阅读一下《The Little Book Of Semaphores》,作者是Allen B.Downy。
14.1.2 RTX任务间信号量的实现 任务间信号量的实现是指各个任务之间使用信号量实现任务的同步或者资源共享功能。 下面我们通过如下的框图来说明一下RTX信号量的实现,让大家有一个形象的认识。
运行条件: 1. 创建2个任务Task1和Task2。 2. 创建信号量可用资源为1。 运行过程描述如下: 1. 任务Task1运行过程中调用函数os_sem_wait获取信号量资源,如果信号量没有被任务Task2占用,Task1将直接获取资源。如果信号被Task2占用,任务Task1将由运行态转到挂起状态,等待资源可用。一旦获取了资源并使用完毕后会通过函数os_sem_send释放掉资源。 2、 任务Task2运行过程中调用函数os_sem_wait获取信号量资源,如果信号量没有被任务Task2占用,Task1将直接获取资源。如果信号被Task2占用,任务Task1将由运行态转到挂起状态,等待资源可以。一旦获取了资源并使用完毕后会通过函数os_sem_send释放掉资源。
上面就是一个简单RTX任务间信号量的使用过程。
14.1.3 RTX中断方式信号量的实现 RTX中断方式信号量的实现是指中断函数和RTX任务之间使用信号量。信号量的中断方式主要是用于实现任务同步,与上个章节讲解事件标志组中断方式是一样的。 下面我们通过如下的框图来说明一下RTX中断方式信号量的实现,让大家有一个形象的认识。
运行条件: 1. 创建1个任务Task1和一个串口接收中断。 2. 信号量的初始值为0,串口中断调用函数isr_sem_send释放信号量,任务Task1调用函数os_sem_wait获取信号量资源。 运行过程描述如下: 1. 任务Task1运行过程中调用函数os_sem_wait,由于信号量的初始值是0,没有信号量资源可用,任务Task1由运行态进入到挂起态。 2. Task1挂起的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中调用函数isr_sem_send释放信号量资源,信号量数值加1,此时信号量计数值为1,任务Task1由挂起态进入到就绪态,在调度器的作用下由就绪态又进入到运行态,任务Task1获得信号量后,信号量数值减1,此时信号量计数值又变成了0。 3. 再次循环执行时,任务Task1调用函数os_sem_wait由于没有资源可用再次进入到挂起态,等待串口释放信号量资源,如此往复循环。
上面就是一个简单RTX中断方式信号量同步过程。实际应用中,中断方式的消息机制切记注意以下四个问题: 1. 中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应。 2. 实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在任务中实现消息处理,这样可以有效的保证中断服务程序的实时响应。同时此任务也需要设置为高优先级,以便退出中断函数后任务可以得到及时执行。 3. 中断服务程序中一定要调用专用于中断的信号量设置函数isr_sem_send。 4. 在RTX操作系统中实现中断函数和裸机编程是一样的。 (1)另外强烈推荐用户将Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407的NVIC优先级分组设置为4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中断优先级的管理将非常方便。 (2)用户要在RTX多任务开启前就设置好优先级分组,一旦设置好切记不可再修改。
|