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);
}








vxWorks中的信号量是一种同步工具,用于协调多个任务之间的访问资源。它可以用来控制对共享资源的访问,以防止资源竞争和数据冲突。 在vxWorks中,有两种类型的信号量二进制信号量和计数信号量二进制信号量用于互斥访问共享资源,当资源被一个任务占用时,其他任务将被阻塞。计数信号量用于多个任务之间的资源共享,它可以指定资源的可用数量,当资源不可用时,任务将被阻塞,直到资源可用。 使用vxWorks信号量时,首先需要创建一个信号量对象,并初始化它的值。可以使用`semBCreate()`函数创建二进制信号量,或使用`semCCreate()`函数创建计数信号量。然后,可以使用`semTake()`函数来获取信号量,表示任务要开始访问资源。如果信号量的值为0,任务将会被阻塞,直到信号量的值大于0。当任务完成对资源的访问后,需要使用`semGive()`函数释放信号量,表示资源可供其他任务使用。 在使用vxWorks信号量时,需要注意以下几点: 1. 保证每个任务在访问资源之前都使用`semTake()`函数获取信号量,以防止资源竞争。 2. 在任务完成对资源的访问后,必须使用`semGive()`函数释放信号量,以便其他任务可以使用资源。 3. 对于二进制信号量,每个任务应该在访问资源之前都获取到信号量,而在访问完成后都释放信号量。而对于计数信号量,任务可以多次获取和释放信号量,直到资源不可用为止。 4. 可以使用信号量来控制任务之间的执行顺序,比如一个任务等待另一个任务完成后才能执行。 总之,vxWorks中的信号量是一种有助于协调多个任务对资源访问的重要工具,通过获取和释放信号量,可以确保对资源的访问按照预期的顺序进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木泽八

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值