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

原创 2006年06月15日 14:33:00

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

相关文章推荐

Linux下的定时器以及POSIX定时器:timer_settime()

Linux下的定时器有两种:1、alarm  如果不要求很精确的话,用alarm()和signal()就够了。  unsigned int alarm(unsigned int seconds)  函...

由浅入深Linux下pthread线程库介绍

  • 2012年02月06日 12:38
  • 150KB
  • 下载

由浅入深Linux下pthread线程库介绍

  • 2011年01月19日 17:10
  • 59KB
  • 下载

关于linux应用层高精度定时器设计(笔记)

目的:协议采样率收发离散度达到10us以下.. 问题:常规运行,为10~30毫秒,目前通过修改极限只能达到1000us.(5分钟)   技术难点:摘自http://www.eefocus.com...

Linux下pthread线程库介绍

1、概述 多线程程序作为一种多任务、并发的工作方式,有以下的优点: 1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标...

关于Linux的应用层定时器

使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务。要达到这一目的,一般有两个常见的比较有效的方法。一个是用 Linux 内部的三个定时器;另一个是用 sleep ...

Linux下posix线程实现的定时器

  • 2006年06月15日 00:00
  • 0B
  • 下载

linux下在应用层打印调用堆栈

如下函数可以在任意函数中打印出当前的调用堆栈 输出到标准输出设备,一般就是命令行了 需要注意的是必须包含下面的标准库头文件 #include void print_trace(void)   { ...
  • namelcx
  • namelcx
  • 2016年08月11日 11:03
  • 938

Linux下实现应用层串口库函数

//serialport.h /************************************************************* FileName : s...
  • sunrier
  • sunrier
  • 2012年06月13日 22:48
  • 3825

Linux下实现应用层串口库函数

//serialport.h [cpp] view plaincopy /*****************************************...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux下利用posix线程库设计自己的应用层timer定时器
举报原因:
原因补充:

(最多只允许输入30个字)