zoukankan      html  css  js  c++  java
  • 【转】VxWorks信号量分析

    Wind内核中有二进制信号量、计数信号量和互斥信号量三种类型,为了是运用程序具有可移植性,还提供了POSIX(可移植操作系统接口)信号量 。在VxWorks中,信号量是实现任务同步的主要手段,也是解决任务同步的最佳选择。

    关于互斥的实现:

    使用二进制信号量可以很方便的实现互斥,互斥是指多任务在访问临界资源时具有排他性。为了使多个任务互斥访问临界资源,只需要为该资源设置一个信号量,相当于一个令牌,那个任务拿到令牌即有权使用该资源。把信号量设置为可用,然后把需要的资源 的任务的临界代码 置于semTake()和semGive()之间即可。

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

    2、信号量属性中的参数为:SEM_Q_PRIORITY。而且在创建信号量的时候必须把信号量置为满SEM_FULL。即信号量可用。

    基本实现互斥模型:

    复制代码
     1 SEM_ID semMutex;
     2 
     3 semMutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
     4 
     5 task(void)
     6 {
     7 
     8       semTake(semMutex, WAIT_FOREVER);//得到信号量,即相当于得到使用资源的令牌
     9 
    10        //临界区,某一个时刻只能由一个任务 访问
    11 
    12        semGive(semMutex);
    13 
    14 }
    复制代码


    关于任务同步的实现

    同步即任务按照一定的顺序先后执行,为了实现任务A和B同步,只需要让任务A和B共享一个信号量,并设置初始值为空,即不可用,将semGive()置于任务A之后,而在任务B之前插入semTake()即可。

    说明:
    1、还是讨论和优先级的关系。由于信号量初始化为空,不可用,所以可能使得优先级反转,即高优先级任务B在等待低优先级任务A释放信号量。只有执行了信号量释放语句semGive()后任务B得到信号量才能执行。

    2、属性参数的设置为SEM_Q_FIFO,SEM_EMPTY;

    实现模型参考

    复制代码
     1 SEM_ID semSync;
     2 
     3 semSync = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
     4 
     5 taskA(void)
     6 {
     7     
     8 
     9     semGive(semSync);      //信号量释放,有效
    10 }
    11 taskB(void)
    12 {
    13 
    14     semTake(semSync, WAIT_FOREVER);   //等待信号量
    15 
    16      .
    17 }
    复制代码

    使用信号量注意事项:

    1、用途不同,信号量属性和初始值不同。

    2、互斥访问资源时,semTake()和semGive()必须成对出现,且先后顺序不能颠倒。

    3、避免删除那些其它任务正在请求的信号量。

    应用:

    1、确保任务优先级不反转

    复制代码
     1 SEM_ID semFs;
     2 SEM_ID semFss;
     3 SEM_ID semFex;
     4 
     5 semFs = semBCreate(SEM_Q_FIFO,  SEM_EMPTY);
     6 semFss = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
     7 semFex = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
     8 
     9 void t_imaGet(void)
    10 {
    11     printf("a   ");
    12     semGive(semFs);   //释放信号量
    13 }
    14 
    15 void t_imaJud(void)
    16 {
    17     semTake(semFs, WAIT_FOREVER);//确保优先级不反转
    18 
    19     printf("jj ");
    20     semGive(semFss);
    21 }
    22 
    23 void t_imaPro(void)
    24 {
    25     semTake(semFss, WAIT_FOREVER);
    26     printf("rr");
    27     semGive(semFex);
    28 }
    29 
    30 void t_imaExc(void)
    31 {
    32     semTake(semFex, WAIT_FOREVER);
    33     printf("Y");
    34 }
    35 
    36 void start(void)
    37 {
    38     int tGetId, tJudId, tProId, tExcId;
    39     tGetId = taskSpawn("tPget", 200, 0, 1000,(FUNCPTR)t_imaGet, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    40     tJudId = taskSpawn("tPjud",201,0,1000,(FUNCPTR)t_imaJud,3,0,0,0,0,0,0,0,0,0); 
    41     tProId = taskSpawn("tPpro",202,0,1000,(FUNCPTR)t_imaPro,3,0,0,0,0,0,0,0,0,0); 
    42     tExcId = taskSpawn("tPexc",203,0,1000,(FUNCPTR)t_imaExc,3,0,0,0,0,0,0,0,0,0);
    43 
    44 }
    复制代码

    以上例子虽然定了各个任务的优先级,但是加上信号量可以 实现同步,而且防止优先级反转的出现。

     
  • 相关阅读:
    ExecuteNonQuery()返回值
    GridView导入至EXCEL (报错处理:只能在执行 Render() 的过程中调用 RegisterForEventValidation)
    mysql 远程登录
    四舍六入 银行家算法
    linux-grep-tail-find
    spring 事务注解
    aop execution 表达式解析
    事务有效条件
    oracle 日期取 月 日
    spring cloud 定时任务
  • 原文地址:https://www.cnblogs.com/zhanjxcom/p/4792653.html
Copyright © 2011-2022 走看看