附上简单的源码[信号量操作实例]
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;
}