Linux下利用posix线程库设计自己的应用层timer定时器
2006-06-15 14:33
405 查看
用管了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
#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时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- 关于linux应用层高精度定时器设计(笔记)
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- [转] Linux应用层的定时器Timer
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux应用层的定时器Timer使用详解
- [转] Linux应用层的定时器Timer
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】
- Linux应用层的定时器Timer使用详解【转】
- Linux应用层的定时器Timer
- epoll定时器实现系列文章:linux c++ 利用timerfd和epoll封装计时器(Timer)类
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- linux驱动之内核定时器驱动设计-- timer
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()
- Linux应用层的定时器Timer使用详解
- Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()