UCOS_II学习笔记---信号量管理之信号量的使用


#include 

#define  TEST_SEM_EN  0 //test switch, 0: off 1:on
#define  TASK_STK_SIZE 128

OS_STK        Task01Stk[TASK_STK_SIZE];
OS_STK        Task02Stk[TASK_STK_SIZE];

static OS_EVENT *sem_p;
static OS_EVENT *sem_v;

static void task_01(void *p_arg);
static void task_02(void *p_arg);


void main(int argc, char *argv[])
{
 OSInit();   

 //create P V semaphore
 sem_p = OSSemCreate(1);
 sem_v = OSSemCreate(1);

 OSTaskCreate(task_01, NULL, (OS_STK *)&Task01Stk[TASK_STK_SIZE-1], (INT8U)10);
 OSTaskCreate(task_02, NULL, (OS_STK *)&Task02Stk[TASK_STK_SIZE-1], (INT8U)11);

 OSStart();                            
}


void task_01(void *p_arg)
{
 INT8U err;
 p_arg = p_arg;
    while (TRUE)                            
 {    
#if TEST_SEM_EN
  OSSemPend(sem_p, 0, &err);
#endif

  OS_Printf("A"); 
  OSTimeDlyHMSM(0, 0, 1, 0); 

#if TEST_SEM_EN
  OSSemPost(sem_v);
#endif
    }
}


void task_02(void *p_arg)
{
 INT8U err;
 p_arg = p_arg;

    while (TRUE)                            
 {    
#if TEST_SEM_EN
  OSSemPend(sem_v, 0, &err);
#endif

  OS_Printf("B"); 
  OSTimeDlyHMSM(0, 0, 3, 0); 
  
#if TEST_SEM_EN
  OSSemPost(sem_p);
#endif
    }
}

不使用信号量运行的结果(将宏TEST_SEM_EN设置为 0)     

UCOS_II学习笔记---信号量管理之信号量的使用_第1张图片

进程同步,使用信号量控制,运行结果(将宏TEST_SEM_EN设置为1)

信号量(Semaphores)

信 号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数 目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore()创建信号量时即要 同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减 1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能在 允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源 计数加1。在任何时候当前可用资源计数决不可能大于最大资源计数。

PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。

P操作 申请资源:

(1)S减1;

(2)若S减1后仍大于等于零,则进程继续执行;

(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。

V操作 释放资源:

(1)S加1;

(2)若相加结果大于零,则进程继续执行;

(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。

对于信号量,uCOS II中共提供了六个函数:OSSemCreate 、OSSemDel、OSSemPend、OSSemPost、OSSemAccept、OSSemQuery。

                         其中我们常用的只有三个即 OSSemCreate 、OSSemPend、OSSemPost 。

      信号量的结构为:
                               typedef struct {
                                   INT8U   OSEventType;                   

                                   INT8U   OSEventGrp;                    

                                   INT16U  OSEventCnt;                    
                                   void   *OSEventPtr;               

                                   INT8U   OSEventTbl[OS_EVENT_TBL_SIZE]; 

                               } OS_EVENT;

          OSSemCreate的函数原型为:OS_EVENT *OSSemCreate(INT16U cnt),cnt 表示在实际使用中有多少个相同的资源,cnt的值就是OSEventCnt的值。

       OSSemPend的函数原型为:void OSSemPend(OS_EVENT *pevent,INT16U timeout,INT8U err),pevent:就是要请求的信号量地址;timeout:请求的超时时间,如果为0表示无限时等待;err:用来返回是否出错。每执行一次 OSSemPend,OSEventCnt就会减1。如果OSEventCnt值为0,执行OSSemPend时,当时任务将因为无法得到相应的资源而被 挂起。


       OSSemPost的函数原型为:INT8U OSSemPost(OS_EVENT *pevent),同样pevent 就是要发送的信号量地址;每执行一次OSSemPost,OSEventCnt就会加1



你可能感兴趣的:(UCOS_II学习笔记---信号量管理之信号量的使用)