【VxWorks操作系统】任务间通信-NO.3.1

目录

1.1 共享数据结构

1.2 互斥和同步

1.2.1 中断锁与延迟

1.2.2 抢占锁与延迟

1.3 信号量

1.3.1 二进制信号量

1.3.1.1 互斥

1.3.1.2 同步

1.3.2 互斥信号量

1.3.2.1 优先级反转

1.3.2.2 安全删除

1.3.2.3 递归资源访问

1.3.3 计数信号量


       任务间的同步和通信是多任务系统的必需功能,VxWorks操作系统以互斥锁信号量实现任务同步,并提供消息传递机制以实现任务通信。

       同步机制主要涉及系统资源共享和事件等待,对于可重入的系统而言,同步分为内核间的同步和应用程序之间的同步,内核同步可以采用中断屏蔽实现,也可利用与应用程序相同的同步原语。

       互斥锁和信号量都存在一个优先级逆转问题,即优先级低的任务拥有高优先级任务所需的资源,从而阻塞了后者的执行。在实时系统中,这种情况必须避免,为此,采用了优先级继承技术,具体实现方法是:在高优先级的任务企图获得被占用的资源时,给占有资源的低优先级任务赋予与自己相同的优先级,这种技术保证了高优先级任务的临界时间。

       任务同步机制对实时任务调度有深远的影响,具体体现在临界时间的满足,优先级动态变化、上下文切换的频率以及任务集的负载等方面。

系统提供了一套丰富的任务间通信机制:

1)共享内存,目的针对共享数据;

2)信号量,基本的同步和互斥;

3)消息队列和管道,在任务间传递信息;

4)信号,针对异常处理。

1.1 共享数据结构

       任务间通信最明显的方式就是共享数据结构,因为系统中所有的任务在同一个线性地址空间中,所以共享数据是很平常的,全局变量,线性缓冲区,循环缓冲区,链表及指针可以被不同上下文运行的代码直接访问。

1.2 互斥和同步

       虽然一个共享的地址空间简化了数据交换,但是为了避免竞争,互锁对内存的访问是关键的,系统提供很多对资源进行访问的函数,不同仅仅在于互斥的粒度,这样的方法包括了禁止中断、禁止抢占、以及使用信号量使用资源。

1.2.1 中断锁与延迟

       最有利的互斥的是禁止中断,这保证了对CPU的独占使用,解决了任务(或中断服务程序)与中断服务程序之间的互斥问题。

funA()

{

        int lock = intLock();

        intUnlock();

}

       对于实时系统来说,这不是一个合适的通用互斥机制,因为这使系统在封锁期间不能对外部时间做出响应,对于任何一个需要立即响应的外部事件来说,中断延时是不能接受的,然而,对一些同中断服务程序ISR的互斥,中断锁有时也是必要的,在任何情况下,都要让中断封锁的时间保持最小。

1.2.2 抢占锁与延迟

     禁止抢占提供了一个稍微宽松的互斥手段:

funA()

{

taskLock();

taskUnlock();

}

       这种方式可以保证没有任何任务可以抢占当前任务,中断服务程序ISR却可以运行,然而,这种方法可能导致一个无法接受的实时响应。在上锁任务离开关键段之前,高优先级的任务将无法运行,即使这个高优先级的任务不干涉该字段。这种互斥十分简单,用户需要将这个阶段保持短小,信号量提供了一种更好的机制。

1.3 信号量

       在Vxworks操作系统中,信号量是高度优化、最快速的任务间通信机制,信号量是实现任务间互斥和同步的主要手段。

      对于互斥,信号量对共享资源的访问进行互锁,提供比中断锁和抢占锁更优化的互斥粒度。

      对于同步,信号量将一个任务的执行与外部时间协调。

内核有三种信号量,分别针对各种不同的问题做优化:

1)二进制信号量。这是最快最通用的信号量,优化了互斥和同步。

2)互斥信号量。一种特殊二进制信号量,针对互斥的内在问题做了优化:优先级继承,安全删除和递归。

3)计数信号量与二进制信号量相似,但跟踪信号发出的次数,对于守护某种资源的多个实例做了优化。

接下来我将详细介绍各个信号量。

1.3.1 二进制信号量

       二进制信号量主要满足任务间的两种协作要求:同步互斥。互斥信号量也是一种二进制信号量,但是它针对互斥问题的特性做了优化,当互斥信号量的高级特性没有必要的时候,通用的二进制信号量也可以用作互斥。

       信号量可以被当做一个可用或者不可用的标志,当一个任务要获取一个二进制信号量的时候,若该信号量可用,则任务继续运行,信号量由可用变为不可用。当信号量不可用时,则任务被放在一个阻塞队列中并在这个信号量上阻塞。

       当一个任务或者中断服务程序释放一个信号量的时候,当信号量可用,则释放信号量没有作用;当信号量不可用并且没有任务阻塞在信号量上,释放信号量使得信号量可用;当信号量不可用并且有任务有任务阻塞在信号量上,释放信号量使得阻塞队列上的第一个任务立刻唤醒变成就绪状态。

1.3.1.1 互斥

       使用二进制信号量的互斥功能时,信号量的初始状态为可用(满)。当一个任务访问共享资源时,它必须首先获得信号量,只要占用该信号量的任务不释放,所有其他访问该资源的任务都将阻塞,当任务完成只使用,释放掉该信号量,允许其他任务使用这个资源。互斥访问需要使用semTake()semGive()配合使用。

SEM_ID semTab;

semTab = semBCreat(SEM_Q_PRIORITY,SEM_FULL);

       然后使用semTake()获取一个信号量来保护临界区,并在退出临界区的时候用semGive()重新给出信号量,二者必须在同一段函数中配套使用如果不配套使用将会带来意想不到的问题,因此在编写代码是尤其注意这里的使用。

semTake(semTab,WAIT_FOREVER);

......

semGive(semTab);

1.3.1.2 同步

       当用于任务同步时,信号量可以代表一个条件或者任务等待的事件。初始化时,信号量不可用(空)。一个任务或者中断服务程序通过释放信号量来标志事件的发生。另一个任务调用semTake()等待信号量,等待的任务阻塞直到事件发生或者信号量被释放。

       要区分互斥和同步,对于互斥,信号量最初是满的,每个任务首先获得信号量,然后访问共享资源,最后释放信号量;对于同步,信号量最初是空的,一个任务等待获得被其他任务或者中断释放的信号量。

1.3.2 互斥信号量

      互斥信号量是一种特殊的二进制信号量,用于解决互斥的内在问题,包括优先级反转,安全删除和对资源的递归访问,互斥信号量最基本的行为和二进制信号量是一致的,只有以下不同:

1)只能用于互斥;

2)只能由获得它的任务释放;

3)不能由一个中断服务程序释放;

4)semFlush操作是非法的;

1.3.2.1 优先级反转

       当一个优先级的任务被强制等待一段不确定的时间以让一个低优先级的任务完成时就发生了优先级反转,场景如下图描述:

       这种情况可能可能会持续发生,导致T1阻塞一段不确定的时间,因此系统将使用优先级继承可以解决这个问题。

       优先级继承保证了一个占有了资源的任务具有阻塞在这个资源上的所有任务重最高的优先级。一旦优先级被提高了,他将保持到所持有的所有信号量都被释放为止。这样这个任务就不会被中间优先级的任务所抢占了。该选项要求与优先级队列(SEM_Q_PRIORITY)一起使用。

semId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);

1.3.2.2 安全删除

       在一个用信号量保护起来的临界段中,需要保护执行的任务不被意外删除,删除一个在临界区执行的任务会带来意想不到的后果,资源可能处于破坏状态,同时受保护的信号量不再可用,直接中止对该资源的所有访问。

       原语taskSafetaskUnsafe提供了一种任务删除的方法,但是在使用互斥信号量选项SEM_DELETE_SAFE时,每次使用semTake()将隐含调用taskSafe(),使用semGive()将隐含调用taskUnsafe()。使用这种方式,任务在占用信号量时不会被删除,该选项由于最终代码进入内核部分较少,因此比使用原语taskSafe()taskUnsafe()更加有效。

semId = semMcreate(SEM_Q_FIFO | SEM_DELETE_SAFE);

1.3.2.3 递归资源访问

       互斥信号量能够递归获得,这意味着持有信号量的任务在最终释放之前能够多次地提取,递归非常适用于一组需要相互调用的子程序同时又需要进行资源互斥访问的情况。由于系统保持跟踪当前哪个任务持有互斥信号量,因此这是能够实现的。

       在释放信号量之前,递归获取的互斥信号量被释放和提取的次数应该相等。这通过一个计数器跟踪实现,每调用semTake()一次计数器加一,每调用semGive()一次计数器减一

1.3.3 计数信号量

       计数器信号量是实现任务同步和互斥的另一种手段,计数器信号量与二进制信号量类似,它还跟踪信号量被释放的次数。每释放一个信号量,计数器加一,每提取一个信号量,计数器减一,当计数器计数为0时,试图提取信号量的任务被阻塞。与二进制信号量一样,如果信号量被释放时存在被阻塞的任务,那么被阻塞的任务将被解除阻塞,然而,与二进制信号量不同的是,如果信号量被释放时不存在阻塞的任务,那么计数器将加一。这意味着一个被释放两次的信号量,可以无阻塞的被提取两次。

      下图给出了初始值为3的计数器信号量被任务提取和释放时的时间顺序。

       上述内容简要介绍了VxWorks操作系统下任务间通信的相关内容,主要就信号量的种类、概念和使用方法做了说明,了解了机理,还是需要各位码农朋友结合实际进行编写和处理。

路漫漫其修远兮,吾将上下而求索。

欢迎大家在评论区讨论提问,我会尽我所能解答疑惑,我是指尖比比,咱们下一期再见!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值