VxWorks主要提供如下API进行信号量的创建、获取和释放:
参数1:SEM_Q_PRIORITY,SEM_Q_FIFO
SEM_Q_PRIORITY(值为0x1):需要获取该信号量的任务基于优先级顺序排列。
SEM_Q_FIFO(值为0x0):需要获取该信号量的任务基于等待任务队列的先进先出顺序排列。
参数2: SEM_FULL,SEM_EMPTY
SEM_Q_FIFO(值为0x0):需要获取该信号量的任务基于等待任务队列的先进先出顺序排列。
参数2: SEM_FULL,SEM_EMPTY
SEM_FULL: 初始化信号量为满(可用),
SEM_EMPTY: 后者初始化信号量为空(不可用)。
(1)semBCreate( ):分配并初始化一个二进制信号量,函数原型为:
SEM_ID semBCreate
(
int options, /*信号量选项*/
SEM_B_STATE initialState /*信号量初始化状态值*/
) ;
(2)semMCreate( ):分配并初始化一个互斥信号量,函数原型为:
SEM_ID semBCreate
(
int options, /*信号量选项*/
SEM_B_STATE initialState /*信号量初始化状态值*/
);
(3)semCCreate( ):分配并初始化一个计数信号量,函数原型为:
SEM_ID semCCreate
(
int options, /*信号量选项*/
int initialCount /*信号量初始计数值*/
) ;
当一个信号量被创建时,它的队列(queue)类型需要被确定。等待信号量的任务队列可以以优先级顺序 (SEM_Q_PRIORITY)或者先到先得方式(SEM_Q_FIFO)排列。
SEM_ID semBCreate
(
int options, /*信号量选项*/
SEM_B_STATE initialState /*信号量初始化状态值*/
) ;
(2)semMCreate( ):分配并初始化一个互斥信号量,函数原型为:
SEM_ID semBCreate
(
int options, /*信号量选项*/
SEM_B_STATE initialState /*信号量初始化状态值*/
);
(3)semCCreate( ):分配并初始化一个计数信号量,函数原型为:
SEM_ID semCCreate
(
int options, /*信号量选项*/
int initialCount /*信号量初始计数值*/
) ;
当一个信号量被创建时,它的队列(queue)类型需要被确定。等待信号量的任务队列可以以优先级顺序 (SEM_Q_PRIORITY)或者先到先得方式(SEM_Q_FIFO)排列。
(4)semDelete( ):删除一个自由的信号量,函数原型为:
STATUS semDelete
(
SEM_ID semId /*要删除的信号量ID号*/
);
(5)semTake( ):占有一个信号量,函数原型为:
STATUS semTake
(
SEM_ID semId /*所要得到的信号量ID号*/
int timeout /*等待时间*/
);
(6)semGive( ):释放一个信号量,函数原型为:
STATUS semGive
(
SEM_ID semId /*所给出的信号量ID号*/
);
(7)semFlush( ):解锁所有等待信号量的任务,函数原型为:
STATUS semFlush
(
SEM_ID semId /*要解锁的信号量ID号*/
);
二进制信号量:
要创建一个发挥互斥作用的二进制信号量一般使用semBCreat(xxx, SEM_FULL)调用,其中的SEM_FULL暗示该信号量用于任务间的互斥(最开始二进制信号量可获得)。对临界区域(critical region)的访问需以semTake和semGive加以保护:
semTake (semMutex, WAIT_FOREVER);
. . /*critical region, only accessible by a single task at a time*/
semGive (semMutex);
semTake (semMutex, WAIT_FOREVER);
. . /*critical region, only accessible by a single task at a time*/
semGive (semMutex);
要创建一个发挥同步作用的二进制信号量一般使用semBCreat(xxx, SEM_EMPTY) 调用,其中的SEM_EMPTY 暗示该信号量用于任务间的同步(即最开始二进制信号量不可获得)。
二进制信号量使用最广泛的一种情况是中断与任务间通信。中断服务程序一般以二进制信号量“通知”对应的任务进行中断后的处理工作,例如:
SEM_ID syncSem;/* ID of sync semaphore */
myTask(void)
{
semTake(syncSem, WAIT_FOREVER); /* wait for event to occur */
printf("my Task got the semaphore/n");
... /* process event */
}
二进制信号量使用最广泛的一种情况是中断与任务间通信。中断服务程序一般以二进制信号量“通知”对应的任务进行中断后的处理工作,例如:
SEM_ID syncSem;/* ID of sync semaphore */
myTask(void)
{
semTake(syncSem, WAIT_FOREVER); /* wait for event to occur */
printf("my Task got the semaphore/n");
... /* process event */
}
eventInterruptSvcRout(void)
{
semGive(syncSem); /* let my Task process event */
...
}
{
semGive(syncSem); /* let my Task process event */
...
}
互斥信号量
互斥信号量可以看作一种特殊的二进制信号量,其支持普通二进制信号量不支持的一些特性,提供优先级继承、安全删除和回归能力。互斥信号量的使用方法和二进制信号量基本类似,但有如下区别:
(1)仅仅被用做互斥,不能提供同步机制;
(2)只能被使用它的任务释放;
(3)中断服务程序(ISR)不能释放它;
(4)不能使用函数semFlush( );
(5)支持使用二进制信号量进行互斥时所不支持的优先级“翻转”。
(1)仅仅被用做互斥,不能提供同步机制;
(2)只能被使用它的任务释放;
(3)中断服务程序(ISR)不能释放它;
(4)不能使用函数semFlush( );
(5)支持使用二进制信号量进行互斥时所不支持的优先级“翻转”。
任务的优先级翻转是指高优先级任务因等待低优先级任务占用的互斥资源而被较低优先级(高于低优先级但低于高优先级)的任务不断抢占的情况。VxWorks操作系统提供优先级继承机制对优先级翻转进行预防。占用互斥资源但优先级较低的任务被暂时地提高到等待该资源的最高优先级任务的优先级。这样,中等优先级的任务将无法抢占原本低优先级的任务,使得低优先级任务能尽快执行,释放出优先级较高的任务所需要的资源。
为了使互斥信号量支持优先级继承支持,我们在调用semMCreate时应使用SEM_Q_PRIORITY和SEM_INVERSION_SAFE选项。互斥信号量提供互斥也需要对临界区域进行保护:
为了使互斥信号量支持优先级继承支持,我们在调用semMCreate时应使用SEM_Q_PRIORITY和SEM_INVERSION_SAFE选项。互斥信号量提供互斥也需要对临界区域进行保护:
semTake (semMutex, WAIT_FOREVER);
. . //critical region, only accessible by a single task at a time .
semGive (semMutex);
. . //critical region, only accessible by a single task at a time .
semGive (semMutex);
计数信号量
计数信号量是任务同步和互斥的另一种实现方式.计数信号量除了保留信号量被释放的次数以外和二进制信号量是一样的。每次信号量被释放(gaven)一次,计数增加;每次信号量被占用(taken)一次,计数减少;当计数减少为0时,要求得到信号量的任务被阻塞(blocked)。二进制信号量是如果一个信号量被释放,有一个任务阻塞等待,则这个任务就被unblock.而计数信号量如果一个信号量被释放,没有任务阻塞等待,则计数增加。这说明一个被释放两次的计数信号量可以被占用(taken)两次,没有阻塞
互斥型信号量必须是同一个任务申请,同一个任务释放,其他任务释放无效。同一个任务能递归申请。
二进制信号量,一个任务申请成功后,能由另一个任务释放。可用于任务同步,也可用于互斥
计数信号量可用于队列数据的存储