. . critical region, only accessible by a single task at a time
semGive (semMutex);
同步协调进程(Synchronization)
semBCreat(SEM_Q_FIFO,SEM_EMPTY), SEM_EMPTY 指明用于任务间同步.
#include "vxWorks.h" #include "semLib.h" SEM_ID syncSem; init ( int someIntNum ) { intConnect (INUM_TO_IVEC (someIntNum), eventInterruptSvcRout, 0); syncSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); taskSpawn ("sample", 100, 0, 20000, task1, 0,0,0,0,0,0,0,0,0,0); } task1 (void) { ... semTake (syncSem, WAIT_FOREVER); printf ("task 1 got the semaphore\n"); ... } eventInterruptSvcRout (void) { ... semGive (syncSem); ... }
semTake(semID,time out)--------有Semaphore空闲,就Take, 如果没有,由time out 定,超时则向下执行。
互斥信号量是一个特殊的二进制信号量,设计用于优先级继承,安全删除和回归。它的使用基本和二进制信号量是类似的。但有以下不同:
1、仅仅被用做互斥。
2、只能被使用它的任务释放.(It can be given only by the task that took it.)
3、ISR 不能释放它。
4、不能使用函数semFlush( )。
优先级反转(Priority Inversion)
优先级反转是指一个任务等待比它优先级低的任务释放资源而被阻塞,如果这时有中等优先级的就绪任务,阻塞会进一步恶化。优先级继承技术可用来解决优先级反转问题。
优先级继承(Priority Inheritance)
优先级继承可用来解决优先级反转问题。当优先级反转发生时,优先级较低的任务被暂时地提高它的优先级,使得该任务能尽快执行,释放出优先级较高的任务所需要的资源。
计数信号量(Counting Semaphores)
计数信号量是任务同步和互斥的另一种实现方式.计数信号量除了保留信号量被释放的次数以外和二进制信号量是一样的。每次信号量被释放(gaven)一次,计数增加;每次信号量被占用(taken)一次,计数减少;当计数减少为0时,要求得到信号量的任务被阻塞(blocked)。二进制信号量是如果一个信号量被释放,有一个任务阻塞等待,则这个任务就被unblock.而计数信号量如果一个信号量被释放,没有任务阻塞等待,则计数增加。这说明一个被释放两次的计数信号量可以被占用(taken)两次,没有阻塞。下面是计数信号量的使用例子:
Semaphore Call Count after Call Resulting Behavior semCCreate( ) 3 Semaphore initialized with initial count of 3. semTake( ) 2 Semaphore taken. semTake( ) 1 Semaphore taken. semTake( ) 0 Semaphore taken. semTake( ) 0 Task blocks waiting for semaphore to be available. semGive( ) 0 Task waiting is given semaphore. semGive( ) 1 No task waiting for semaphore; count incremented.
消息队列(Message queues)
消息队列(Message queues)现实的实时应用由一系列互相独立又协同工作的任务组成。信号量为任务间同步和联锁提供了高效机制。在VxWorks中,用于但一CPU任务之间通信主要(primary)的机制是消息队列。消息队列允许一定数量不同长度的消息进行排列。任何任务或中断服务程序(ISR)能够发送消息给消息队列。任何任务可以从消息队列接受消息。多任务可以从同意消息队列发送和接受消息。两个任务之间的全双工(Full-duplex)通信需要针对不同方向的两个消息队列。
消息队列函数介绍
msgQCreate( ) 创建斌初始化一个消息队列
msgQDelete( ) 终止并释放一个消息队列
msgQSend( ) 发送一个消息到消息队列
msgQReceive( ) 从消息队列接受一个消息
消息队列是由函数msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY)创建。它的参数MAX_MSGS指定了消息队列中可允许最多可以排列的消息数和每个消息允许的最大的字节数MAX_MSG_LEN。
一个任务或中断服务程序(ISR)用函数msgQSend( )发送一个消息到消息队列。如果没有任务等待消息队列的消息,这个消息被添加消息缓存的队列里。如果某些任务已经在等待消息队列中的消息,消息立刻被传递给第一个等待的消息的任务。
一个任务用函数msgQReceive( )从消息队列得到一个消息。如果消息队列缓存中有消息存在,第一个消息立刻出列并回到调用处(caller).如果没有消息存在,则任务(calling task)停止(blocks)并被添加到等待消息的任务队列中。这个等待的任务队列按照优先级或先进先出(FIFO)规则排列,这个规则有消息队列创建时所指定。
等待时间限制(time out)
msgQSend( ) 和 msgQReceive( )都有时间限制参数。当发送一个消息,如果消息队列缓存这时没有空间,这个参数指定允许等待的时间(ticks数),直到队列缓存有空间来接收消息。当接收消息时,如果消息队列没有消息,这个参数指定允许等待的时间(ticks数),直到消息队列有消息。
#include "vxWorks.h" #include "msgQLib.h" #define MAX_MSGS (10) #define MAX_MSG_LEN (100) MSG_Q_ID myMsgQId; task2 (void) { char msgBuf[MAX_MSG_LEN]; if (msgQReceive(myMsgQId, msgBuf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR) return (ERROR); printf ("Message from task 1:\n%s\n", msgBuf); } #define MESSAGE "Greetings from Task 1" task1 (void) { if ((myMsgQId = msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY)) == NULL) return (ERROR); if (msgQSend (myMsgQId, MESSAGE, sizeof (MESSAGE), WAIT_FOREVER, MSG_PRI_NORMAL) == ERROR) return (ERROR); }
管道(Pipes)
管道对消息队列提供了一个可供选择的接口,VxWorks的I/O系统。管道是虚拟的I/O设备,由驱动pipeDrv管理。函数pipeDevCreate()创建一个管道设备,这个调用指定管道的名字,能被排列的最多的消息数,和每个消息允许的长度。
status = pipeDevCreate ("/pipe/name", max_msgs, max_length);
被创建的管道是一个通常命名(named)的I/O设备,任务能用标准的I/O函数打开,读,写管道,并能调用ioctl例程。当任务试图从一个空的管道中读取数据,或向一个满的管道中写入数据时,任务被阻塞。和消息队列一样,ISR可以向管道写入,但不能从管道读取。做为I/O设备,管道提供了消息队列所没有的重要特性,调用select()。