关闭

Linux下利用posix线程库设计自己的应用层timer定时器

标签: timerlinuxstructnullsignalmakefile
2920人阅读 评论(1) 收藏 举报

用管了vxWorks下面的定时器转到Linux之后发现麻烦了很多,想想用posix的线程库可以实现自己的timer定时器,这样用起来就方便了很多,原理实际很简单,使用posix的conditional信号就可以了,不多说了,看代码吧就:

#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <semaphore.h>
#include <sys/time.h>

#include "timerLib.h"

static struct TIMER_EVENT *ptimer_head = NULL;

void *timer_task_thread(void *args)
{
 int ret;
 time_t t;
 struct TIMER_EVENT *ptimer;
 pthread_t taskID;
 struct timespec cond_time; 
 long sec;
 long usec;

 ptimer = (struct TIMER_EVENT *)args;

 if (ptimer->timevalue > 1000000)
 {
  sec = (ptimer->timevalue/1000000);
  usec = (ptimer->timevalue%1000000);
 }
 else
 {
  sec = 0;
  usec = ptimer->timevalue;
 }
 
 taskID = pthread_self();
 pthread_detach(taskID);
 while(1)
 {
  time(&t);
   
  cond_time.tv_sec = t+sec;
  cond_time.tv_nsec = usec*1000;   
  ret = pthread_cond_timedwait(&ptimer->cond,&ptimer->mutex, &cond_time);
  if (ret == 0)
  {
   if (ptimer->live == 0)
   {
    free(ptimer);
    pthread_exit((void *)NULL);
   }
  }
  else if (ret == ETIMEDOUT)
  {
   ptimer->func(ptimer->name);
  }   
  pthread_mutex_unlock(&ptimer->mutex);
 }
}

static void add_timer_tail(struct TIMER_EVENT *new)
{
 struct TIMER_EVENT *ptemp;
 
 assert(new != NULL);

 if (ptimer_head == NULL)
 {
  new->prev=new->next = NULL;
  ptimer_head = new;
  return;
 }
 
 for(ptemp=ptimer_head; ptemp->next!=NULL; ptemp=ptemp->next);

 ptemp->next = new;
 new->prev = ptemp;
 new->next = NULL;
}

void del_timer(TIMERID id)
{
 struct TIMER_EVENT *ptemp;

 for(ptemp=ptimer_head; ptemp!=NULL; ptemp=ptemp->next)
 {

      pthread_cleanup_push( (void(*)(void *))pthread_mutex_unlock, (void *)&(ptemp->mutex));
  pthread_mutex_lock(&ptemp->mutex);
  if (ptemp->id == id)
  {
   /* Delete header */
   if (ptemp == ptimer_head)
   {
    if (ptemp->next != NULL)
    {
     ptemp->next->prev = NULL;
     ptemp->live = 0;
     ptimer_head = ptemp->next;
     pthread_cond_signal(&ptemp->cond);
     return;
    }
    else
    {
     ptemp->live = 0;
     ptimer_head = NULL;
     pthread_cond_signal(&ptemp->cond);
     return;
    }
   }
   else if (ptemp->next == NULL)  /* delete tail */
   {
    ptemp->live = 0;
    ptemp->prev->next = NULL;
    pthread_cond_signal(&ptemp->cond);
    return;
   }
   else /* normal */
   {
    ptemp->live = 0;
    ptemp->prev = ptemp->next;
    pthread_cond_signal(&ptemp->cond);
    return;
   } 
  }
  pthread_cleanup_pop( 1 ); 
 }
}

TIMERID add_timer(char *name, long timevalue, void *func)
{
 struct TIMER_EVENT *ptimer;
 pthread_t taskID;
 int ret;
 struct TIMER_EVENT *ptemp;
 int dirty;

 ptimer = (struct TIMER_EVENT *)malloc(sizeof(struct TIMER_EVENT));
 if (ptimer == NULL)
 {
  return (-1);
 }
 
 pthread_mutex_init(&ptimer->mutex, NULL);
 pthread_cond_init(&ptimer->cond, NULL); 
 ptimer->live = 1; 
 ptimer->func = func;
 ptimer->timevalue = timevalue;
 do {
  ptimer->id = rand();
  dirty = 0;  
  for(ptemp=ptimer_head; ptemp != NULL; ptemp=ptemp->next)
  {
   if( ptemp->id == ptimer->id)
   {
    dirty = 1;
    break;
   }
  }
  
 } while(dirty == 1);
 
 if (name != NULL)
 {
  sprintf(ptimer->name, "%s", name);
 }
 else
 {
  sprintf(ptimer->name, "timer%d", ptimer->id);
 }
 
 ret = pthread_create(&taskID, 0, timer_task_thread, (void *)ptimer);
 if (ret < 0)
 {
  perror("pthread_create");
  free(ptimer);
  return (-1);
 }
 add_timer_tail(ptimer);

 return ptimer->id;
}

头文件定义: #ifndef __TIMER_LIB_H__ #define __TIMER_LIB_H__ typedef int TIMERID; struct TIMER_EVENT { struct TIMER_EVENT *prev, *next; TIMERID id; char name[64]; int live; pthread_mutex_t mutex; pthread_cond_t cond; long timevalue; void (*func)(void *args); }; /* Add a timer with name, timevalue(uSeconds) and handler */ TIMERID add_timer(char *name, long timevalue, void *func); /* Delete a timer with id */ void del_timer(TIMERID id); #endif /* __TIMER_LIB_H__ */ 测试主程序及编译Makefile: #include #include #include #include #include "timerLib.h" void timer_handler1(void) { printf("Hello timer.../n"); } void timer_handler2(void) { printf("Hello timer2222222222.../n"); } int main(int argc, char *argv[]) { TIMERID id1, id2; id1 = add_timer("test", 3000000, timer_handler1); id2 = add_timer("test1", 10000000, timer_handler2); for (;;) { switch(getchar()) { case 'l': case 'L': break; default: break; } } return 0; } Makefile: ##Timer library test CC=gcc C_FLAGS = -Wall -O2 LD_FLAGS = -lpthread all: test test: timerLib.o test.o $(CC) $^ $(LD_FLAGS) -o test timerLib.o: timerLib.c timerLib.h $(CC) $(C_FLAGS) -c timerLib.c test.o: test.c timerLib.h $(CC) $(C_FLAGS) -c test.c clean: rm -f *.o test
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:40737次
    • 积分:579
    • 等级:
    • 排名:千里之外
    • 原创:14篇
    • 转载:5篇
    • 译文:0篇
    • 评论:13条
    最新评论