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

简介: 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()不产生任何影响。

 

微信图片_20230116140915.png

互斥模型程序说明:


<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);
}
目录
相关文章
|
12月前
|
存储 Linux
|
3月前
|
Linux 调度
Linux0.11 信号(十二)(下)
Linux0.11 信号(十二)
25 1
|
2月前
|
Linux
linux内核 —— 读写信号量实验
linux内核 —— 读写信号量实验
|
3月前
|
存储 Unix Linux
Linux0.11 信号(十二)(上)
Linux0.11 信号(十二)
28 0
|
4月前
|
安全 Linux 数据格式
【Linux】进程通信----管道通信(下)
【Linux】进程通信----管道通信(下)
35 0
|
4月前
|
Unix Linux
【Linux】进程通信----管道通信(上)
【Linux】进程通信----管道通信(上)
42 0
|
5月前
|
消息中间件 API
【FreeRTOS(二)】FreeRTOS新手入门——计数型信号量和二进制信号量的基本使用并附代码解析
【FreeRTOS(二)】FreeRTOS新手入门——计数型信号量和二进制信号量的基本使用并附代码解析
|
6月前
LabVIEW编程NI 6602计数器DMA冲突例程与相关资料
LabVIEW编程NI 6602计数器DMA冲突例程与相关资料
52 7
|
存储 缓存 Linux
线程概念与控制【Linux】
线程概念与控制【Linux】
72 0
|
Linux Shell 程序员
Linux之进程信号(上)(一)
Linux之进程信号(上)(一)
119 0