vxworks系统学习----二进制信号量

1 信号量概念

在vxworks中使用信号量工具对互斥与任务同步进行操作。在wind内核中存在二进制信号量、互斥信号量及计

数信号量。互斥:当共享地址空间进行简单的数据交换时,为避免竞争需要对内存进行互锁,即多个任务访问共享内存时,体现出来的排它性。使用二进制信号量就可以很方便地实现互斥,当多个任务访问共享资源时,对该资源设置一个信号量(相当于令牌),那么拿到该令牌的任务就可以独享该资源。

2 二进制信号量互斥实现说明与代码模型参考

二进制信号量需要的系统开销最小,因而特别适合于高性能的需求。

注意:
(1)互斥中的信号量与任务优先级的关系:任务的调度还是按照任务优先级进行,但是在使用内存的时候只有一个任务获得信号量,也就是说还是按照任务优先级获得信号量从而访问资源。只有当前使用资源的任务使用semGive()释放信号量后,其它任务按照优先级才可以获得信号量。

(2)信号量属性中的参数为:SEM_Q_PRIORITY。而且在创建信号量的时候必须把信号量置为满SEM_FULL,即信号量可用,等待信号的任务可以根据优先级顺序(SEM_Q_PRIORITY)或者先进先出(SEM_Q_FIFO)进行排队。

如图1所示,使用semBCreate(),分配并初始化一个二进制信号量,返回值为一信号量ID,为其他信号量控制函数的应用提供句柄,并设置资源可用(full)还是不可用(empty)。

任务可以调用semTake()函数提取二进制信号量,如果信号量可用(full)那么将变得不可用(empty),同时任务继续执行。如果信号量不可用(empty),调用semTake()函数的任务将被放到一个阻塞队列中,处于等待信号量可用的状态(pending挂起)。

semGive()可用于释放信号量。若信号量不可用(empty)并且没有任务在等待它,那么该信号量将变得可用(full),若信号量不可用(empty)并且有任务在等待它,那么 阻塞队列中的第一个任务将得到该信号量变得不阻塞, 同时 该信号量仍旧不可用(empty),若信号量可用(full),调用semGive()不产生任何影响。

                                                

图1

互斥模型程序说明:

<span style="color:#FFCCCC;"><span style="color:#330033;">SEM_ID semMutex;

semMutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);//优先级顺序排队,信号量可用

task(void)
{

      semTake(semMutex, WAIT_FOREVER);//得到信号量,即相当于得到使用资源的令牌

       //临界区,某一个时刻只能由一个任务访问

       semGive(semMutex);

}</span></span>

3 二进制信号量任务同步实现

任务同步:任务利用信号量控制自己的运行进度,按照一定的先后顺序执行。例如为了任务A与B同步,A与B可以共享一个信号量,初始值设置为不可用,在A之后调用semGive在B之前调用semTakeSEM_ID 即可。

SEM_ID  semSync;

semSync = semBCreate(SEM_Q_FIFO, SEM_EMPTY);

taskA(void)

{ semGive(semSync); //信号量释放

}taskB(void){ semTake(semSync, WAIT_FOREVER); //获取信号量}

 
  

注意:

(1)创建的新的信号量初始值应当为不可用(empty),因而可能使得优先级翻转,即高优先级任务在低优先级任务之后执行;

(2)属性参数设置:SEM_Q_FIFO,SEM_EMPTY。在不同的TASK中分别单独调用semTake(),semGive()且先后顺序不能颠倒。

(3)禁止删除那些任务正在请求信号量。

(4)semTake()不可以在中断中调用,因为调用semTake()的函数可能被挂起,而中断不可以被挂起。semGive()可以在中断中调用

例子程序:

SEM_ID semFs;
SEM_ID semFss;
SEM_ID semFex;
semFs = semBCreate(SEM_Q_FIFO,  SEM_EMPTY);
semFss = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
semFex = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
void t_imaGet(void)
{
    printf("task t_imaGet get the semaphore\n ");
    semGive(semFs);   //释放信号量
}

void t_imaJud(void)
{
    semTake(semFs, WAIT_FOREVER);//确保优先级不反转
    printf("task  imaJud get the semaphore\n");
    semGive(semFss);
}

void t_imaPro(void)
{
    semTake(semFss, WAIT_FOREVER);
    printf("task imaProget the semaphore\n");
    semGive(semFex);
}

void t_imaExc(void)
{
    semTake(semFex, WAIT_FOREVER);
    printf("task imaExcthe semaphore\n");
}

void start(void)
{
    int tGetId, tJudId, tProId, tExcId;
    tGetId = taskSpawn("tPget", 200, 0, 1000,(FUNCPTR)t_imaGet, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    tJudId = taskSpawn("tPjud",201,0,1000,(FUNCPTR)t_imaJud,3,0,0,0,0,0,0,0,0,0); 
    tProId = taskSpawn("tPpro",202,0,1000,(FUNCPTR)t_imaPro,3,0,0,0,0,0,0,0,0,0); 
    tExcId = taskSpawn("tPexc",203,0,1000,(FUNCPTR)t_imaExc,3,0,0,0,0,0,0,0,0,0);
}








发布了27 篇原创文章 · 获赞 19 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/muaxi8/article/details/52064957