用信号量实现实时多任务管理(三)

附上简单的源码[信号量操作实例]

1,头文件

/*******************************************************************
文件名    : HttpRT_process.h
文件描述  : http Real-time process
作者      : stz
创建时间  : 2009年3月6日
修改记录  :
*******************************************************************/
#ifndef _HTTP_RT_PROCESS_H_
#define _HTTP_RT_PROCESS_H_

#define  MAX_TASK  100   /*循环队列中最大任务数目*/
#define  WORK_THREAD  5
#define  SEM_NUM     (2+ WORK_THREAD)
#define  SEM_CYCLE       0
#define  SEM_DISTRIB      1
#define  SEM_WORK_BASE   2

typedef struct tagHttpTask
{
    ULONG ulDstModName;                             /*http://10.10.10.100:/pub/12345.tar */
    CHAR  szFilePathName[MAX_FILENAMELEN+1]; /*szFilePathName = pub/12345.tar */
    
}HTTP_TASK_S;

typedef struct tagCycleQueue
{
    int  iwtFront;
    int  irdRear;
    HTTP_TASK_S  stTask[MAX_TASK];
}CYCLE_QUEUE_S;

/* ----------------- 公共接口 --------------------*/
extern BOOL HttpRT_process(HTTP_TASK_S szHttpTask);
extern BOOL InitHttpRT_process();
extern void DelSemAll();

//#define _DEBUG_
 #ifdef _DEBUG_
   #define debug  printf("Line:%d  in file  %s\n",__LINE__,__FILE__);
 #else
   #define debug
 #endif
#endif


2,源文件

/*******************************************************************
文件名    : HttpRT_process.cpp
文件描述  : http Real-time process
作者      : stz
创建时间  : 2009年3月6日
修改记录  :
*******************************************************************/

#include "HttpRT_process.h"

/****   global  *********/
static CYCLE_QUEUE_S cq ={0};                /*初始化循环队列*/

/*---------信号量相关变量------------*/
key_t SemKey = 4567;

union semun
{
    int val;
    unsigned short *array;
}arg;

static int semid = -1;
unsigned short SemArray[SEM_NUM];


/*-------------初始化工作线程---------------------*/
static HTTP_TASK_S szGetTask[WORK_THREAD] = {{0}};/*为每个线程分配一个任务结构,每个线程从各自的结构中获得任务*/
static int busy[WORK_THREAD] = {0};  /*标识当前工作线程状态,为0空闲,为1要干活了*/


/*---mod reg----*/
const char *ModName[WORK_THREAD] = {"Tsk0","Tsk1","Tsk2","Tsk3","Tsk4"/*,Tsk5,...*/};/*工作线程的模块名字*/
                                                                                     /*每个工作线程都可以有自己发送消息的模块名 */
GOS_DL_S TaskProcesModi[WORK_THREAD];                                               /*设定有5个工作线程*/

                                                                                     

/****** text   ****/
BOOL IsEmpty()
{
   if (cq.irdRear == cq.iwtFront)
    return 1;
   else return 0;
}

BOOL IsFull()
{
   if ((cq.iwtFront + 1)%MAX_TASK == cq.irdRear)
    return 1;
   else return 0;
}
BOOL Add2CQ(HTTP_TASK_S szHttpTask)
{
   if (IsFull())
    return 0;
   cq.stTask[cq.iwtFront] = szHttpTask;
   cq.iwtFront = (cq.iwtFront + 1) % MAX_TASK;
   printf("Add to CycleQueue:%s\n",szHttpTask.szFilePathName);
   return 1;
}
BOOL GetFromCQ(HTTP_TASK_S &szHttpTask)
{
   if (IsEmpty())
    return 0;
   memcpy(&szHttpTask,&(cq.stTask[cq.irdRear]),sizeof(HTTP_TASK_S));
   cq.irdRear =(cq.irdRear +1 ) % MAX_TASK;
   printf("Get from  CycleQueue:%s\n",szHttpTask.szFilePathName);
   return 1;
}

BOOL InitSempSet()/*Initial the Semphore*/
{
    int i = 0;
    
    if ((semid = semget(SemKey,SEM_NUM,0666|IPC_CREAT)) == -1)
	{
		perror("semget!");
		return 0;
	}

    SemArray[SEM_CYCLE] = 0;
    SemArray[SEM_DISTRIB] =  WORK_THREAD;
    for (i = 0; i< WORK_THREAD; i++)
        SemArray[SEM_WORK_BASE+i] = 0;
    arg.array = SemArray;
 	if ( semctl(semid,0,SETALL,arg) == -1)
 	{
 		perror("semctl123!");
 		return 0;
 	}

    return 1;
}
int GetVal()
{ 
    #ifndef _DEBUG_
        return 1;
    #endif
    int i;
    arg.array = SemArray;
    for (i=0;i<7;i++)
     arg.array[i] = 0;
 	if ( semctl(semid,0,GETALL,arg) == -1)
 	{
 		perror("semctl123!");
 		return 0;
 	}
    for (i=0;i<7;i++)
      printf("%d %c",arg.array[i],i==6?'\n':'#');
    return 1;
}
BOOL Wait(unsigned short sem_num)/*对sem_num的值做等待信号量操作*/
{
  struct sembuf sop_wait;
  sop_wait.sem_num = sem_num;
  sop_wait.sem_op = -1;
  sop_wait.sem_flg = 0;

  if (-1 == semop(semid,&sop_wait,1))
	  {
			perror("semop(sop_wait)");
            return 0;
	  }

   return 1;
}
BOOL Signal(unsigned short sem_num)/*对sem_num的值做通知信号量操作*/
{
  struct sembuf sop_signal;
  sop_signal.sem_num = sem_num;
  sop_signal.sem_op = 1;
  sop_signal.sem_flg = 0;
 
   if (-1 == semop(semid,&sop_signal,1))
   {
			perror("semop(sop_signal)");
            return 0;
	}

   return 1;
}
void DelSemAll()
{
   if (semctl(semid,0,IPC_RMID) == -1)
    {
  	  perror("semctl(IPC_RMID)");
  	  //exit(1);
    }
   return;
}

BOOL GetIdleWork(int &getIdle) /*获得空闲的任务线程的busy状态*/
{
    int i = 0 ;

    for (i=0;i<WORK_THREAD;i++)
     if (!busy[i])
      {
         getIdle = i;
         return 1;
      }
     return 0;
}
BOOL RegLocalMod()/*注册模块*/
{
    ULONG ulRet = 0;
    int i = 0;
    
    for (;i<WORK_THREAD;i++)
    {
        TaskProcesModi[i].ulModName = GOS_MOD_NAME_STR_TO_UL(ModName[i]);

        ulRet = GOS_ModInit(TaskProcesModi[i].ulModName, GOS_MOD_MODE_GLOBAL, &(TaskProcesModi[i].ulModId));
        if(GOS_OK != ulRet)
        {
            /* 返回失败值, 已分配资源由操作系统来统一释放 */
            GOS_LogInfoOut("Failed to call GOS_ModInit.\r\n");
            return GOS_ERR;
        }
         /* 注册服务器模式通讯模块,侦听消息处理DL_RcvMsg */
        ulRet = MSW_RegModComm(TaskProcesModi[i].ulModId, NULL, NULL);
        if(GOS_OK != ulRet)
        {
            /* 返回失败值, 已分配资源由操作系统来统一释放 */
            GOS_LogInfoOut("Failed to call MSW_RegModComm.\r\n");
           return GOS_ERR;
        }
       
     }
   return GOS_OK;
}
void SendMsg(int Tski,HTTP_TASK_S &szHttpTask)/*发送Tski的消息,其消息数据为szHttpTask*/
{     
     MSW_MSG_HDR_S* pstMsgHdr= NULL;
     
     pstMsgHdr = (MSW_MSG_HDR_S *)GOS_Malloc(TaskProcesModi[Tski].ulModId, sizeof(MSW_MSG_HDR_S) + strlen(szHttpTask.szFilePathName)+1);
     memset(pstMsgHdr,0,sizeof(MSW_MSG_HDR_S) + strlen(szHttpTask.szFilePathName)+1);
    
     pstMsgHdr->ulDstModName = szHttpTask.ulDstModName;
     pstMsgHdr->ulMsgLen = strlen(szHttpTask.szFilePathName)+1;
     pstMsgHdr->ulSrcModName = TaskProcesModi[Tski].ulModId;
     pstMsgHdr->ulType = CMD_RETURN;
     strcpy((CHAR*)(pstMsgHdr+1),szHttpTask.szFilePathName);
     GetVal();
     printf("Task%d Send Msg: %s\n",Tski,(CHAR*)(pstMsgHdr+1));
     
    if ( GOS_OK != MSW_SendMsg(TaskProcesModi[Tski].ulModId,pstMsgHdr)) /* todo :send msg*/
    {
        GOS_LogInfoOut("Failed to send back msg.\r\n");
       if ( NULL != pstMsgHdr)
       {
          GOS_Free(pstMsgHdr);
          pstMsgHdr = NULL;
       }                    
    }
 
   if ( NULL != pstMsgHdr)
   {
      GOS_Free(pstMsgHdr);
      pstMsgHdr = NULL;
   }
}

void* TaskProces(void*id)/*任务线程*/
{
    char pacCommand[DL_CMD_LEN] = {0};
    int Tski = (int)id;
    static int cnt = 0;

    cnt++;
    //printf("cnt---TaskProces-Start ok-----%d  Tsk =%d \n",cnt,Tski);
  
    while(1)
    {         
       Wait(Tski+SEM_WORK_BASE);/*任务线程初始状态为等待*/
       if (busy[Tski]) 
       {
          //printf("sem ---%d-id doing work ---- The busy value is %d\n \n",Tski+SEM_WORK_BASE,busy[Tski]);
          GetVal();
          snprintf(pacCommand,DL_CMD_LEN,"wget -P %s -c http://%s/%s/%s 2>/dev/null",
                          HTTP_DOWNLOAD_FILE_PATH,HTTP_SERVER_IP,HTTP_SERVER_PATH,szGetTask[Tski].szFilePathName);/*目前是文件的名字*/
          // printf("cmd Sem[%d]-- %s  Start...\n",Tski+SEM_WORK_BASE,pacCommand);
         
          system(pacCommand);
          SendMsg(Tski,szGetTask[Tski]);
       
          //printf("sem ---%d-work has been done \n",Tski+SEM_WORK_BASE);
          busy[Tski] = 0;
          Signal(SEM_DISTRIB);
       }    
    }
   return NULL;
}

void* DistribProcess(void*arg)
{
    int getIdle = -1;
    HTTP_TASK_S szHttpTask = {0};
       
    while(1)
    {
      debug;
      Wait(SEM_CYCLE);/*分发线程。在循环队列中没有数据时,为等待状态*/
      Wait(SEM_DISTRIB);
     
      debug;
      GetIdleWork(getIdle);
      GetVal();
     
      GetFromCQ(szHttpTask);
      /*cp data to TaskProcesi,i is getIdle*/
      memcpy(&szGetTask[getIdle],&szHttpTask,sizeof(HTTP_TASK_S));
      printf("Sem : %d is set to 1\n\n\n",getIdle+SEM_WORK_BASE);
      GetVal();
      busy[getIdle] = 1;
      Signal(getIdle+SEM_WORK_BASE);
   
   }
   return 0;/*失败*/
}

BOOL InitHttpRT_process() /*初始化本模块的接口*/
{
    pthread_t pthread_id_Distrib;
    int i = 0;
           
    if (!InitSempSet())
      return 0;

    if (GOS_OK != RegLocalMod())
        return 0;
    
    if (pthread_create(&pthread_id_Distrib,NULL,DistribProcess,NULL))/*创建一个分发线程*/
       return 0;
       
    for (i= 0;i <WORK_THREAD;i++) /*创建WORK_THREAD个任务线程*/
        {
           pthread_t pthread_id_worki;
           pthread_create(&pthread_id_worki,NULL,TaskProces,(void*)i);
         }
 
    return 1;
}
BOOL HttpRT_process(HTTP_TASK_S szHttpTask)  /*本模块接收数据的接口*/
{ 
   
    if (!Add2CQ(szHttpTask))
      return 0;/*Cq is full*/
    GetVal();
    debug;
    Signal(SEM_CYCLE);
    GetVal();
    debug;
    return 1;
}


转载于:https://my.oschina.net/stz/blog/726057

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值