VxWOrks信号量

来源:互联网 发布:不吃肉 知乎 编辑:程序博客网 时间:2024/05/21 10:09

VxWOrks信号量

信号量允许多个任务相互协调其活动。任务间最直接的通信方式就是共享各种各样的数据。由于VxWorks使用单地址空间,所有的任务存在于一个单一的线性地址空间结构中共享数据结构也就非常容易实现。全局变量,各类缓冲,链表和指针都可以被运行在不同任务上下文直接引用。对于共享的数据,需要保证对其互斥访问。比如信号量就是实现临界区互斥访问的机制中的一种。

信号量控制相关函数

semTake:任务使用semTake函数提取一个信号量,其结果取决于调用时该二进制信号量是是否可用。如果可用,任务将变得不可用,任务继续执行。如果任务不可用,则任务被挂起到任务阻塞队列,直到该信号量可用。

semGive:当任务释放一个二进制信号量要调用semGive(), 其结果也要依赖于调用时刻该信号量是否可用。如果可用,本次释放不起任何作用,信号量不可用,并且有一个或多个任务等待该信号量,那么阻塞队列中的第一个任务解除阻塞,而信号量任然不可用。

VxWorks信号量实例

#include <VxWorks.h>#include <taskLib.h>#include <semLib.h>#include <stdio.h>#define ITER    10SEM_ID sem_binary;int globe = 0;static void taskone(void);static void tasktwo(void);int main(void){    int taskIdone;    int taskIdtwo;    /*create and initlize a binary semaphore*/    sem_Binary = semBcreate(SEM_Q_FIFO, SEM_FULL);    /*extract a semaphore*/    semTake(sem_Binary, WAIT_FOREVER);/*第一次使用semTake函数,信号量变得不可用,主任务继续执行*/    taskIdone = taskSpawn("task1",90,0x100,taskone,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0);    taskIdtwo = taskSpawn("task2",90,0x100,tasktwo,                0, 0, 0, 0, 0, 0, 0, 0, 0, 0);    return 0;}static void taskone(void){    int i;    for(i=0; i<ITER; i++)    {      /*第二次使用semTake函数,将该任务(taskone)设为阻塞状态*/      semTake(sem_Binary, WAIT_FOREVER);/      printf("I am taskone and globe = %d......\n",++globe);      semGive(sem_Binary);    }}static void tasktwo(void){    int i;    /*释放信号量,t处于阻塞状态的taskone开始执行*/    semGive(sem_Binary);    for(i=0; i<ITER; i++)    {      /*信号量可用的状态下semTake将其便变为不可用,任务继续执行*/      semTake(sem_Binary, WAIT_FOREVER);      printf("I am tasktwo and globe = %d......\n",++globe);      semGive(sem_Binary);    }}

程序输出的结果是:

I am taskone and globe = 1 ......I am taskone and globe = 2 ......I am taskone and globe = 3 ......I am taskone and globe = 4 ......I am taskone and globe = 5 ......I am taskone and globe = 6 ......I am taskone and globe = 7 ......I am taskone and globe = 8 ......I am taskone and globe = 9 ......I am taskone and globe = 10 ......I am tasktwo and globe = 9 ......I am tasktwo and globe = 8 ......I am tasktwo and globe = 7 ......I am tasktwo and globe = 6 ......I am tasktwo and globe = 5 ......I am tasktwo and globe = 4 ......I am tasktwo and globe = 3 ......I am tasktwo and globe = 2 ......I am tasktwo and globe = 1 ......I am tasktwo and globe = 0 ......

程序分析

这里来分析一下上述程序的执行过程,首先在main函数中先创建一个信号量,然后第一次调用semTake函数,由于此时信号量为可用状态,所以这里将其设为不可用,任务继续向后执行;
main函数中使用taskSpawn函数创建任务1 ( taskone ),在任务一当中调用semTake函数。由于上面已经将信号量设为不可用。所以这里调用semTake将会是任务taskone处于阻塞状态。
主任务继续执行,创建任务2 ( tasktwo ), 在任务2中首先调用semGive函数,此时由于任务一处于阻塞状态。所以再执行完semGive函数之后任务1开始执行,在for循环中,先将信号量设为不可用状态,printf函数执行完成再将信号量设为可用。即我们所看到的的globe从0加到10。
由于任务1和任务2优先相同,所以等任务1执行完成之后任务2开始执行。即可以解释为什么输出如上面。

原创粉丝点击