天天看点

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

用管了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)

  {

   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) 

   {

    ptemp->live = 0;

    ptemp->prev->next = NULL;

    pthread_cond_signal(&ptemp->cond);

    return;

   }

   else

   {

    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); }; TIMERID add_timer(char *name, long timevalue, void *func); void del_timer(TIMERID id); #endif 测试主程序及编译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

继续阅读