方法一:使用信号量SIGALRM + alarm()
这种方式的精度能达到1秒,其中利用了*nix系统的信号量机制,首先注册信号量SIGALRM处理函数,调用alarm(),设置定时长度,代码示例如下:
#include <stdio.h>#include <signal.h>void timer(int sig){if(SIGALRM == sig){printf("timer\n");alarm(1); //we contimue set the timer}return ;}int main(){signal(SIGALRM, timer); //relate the signal and functionalarm(1); //trigger the timergetchar();return 0;}
方法二:使用RTC机制
RTC机制利用系统硬件提供的Real Time Clock机制,通过读取RTC硬件/dev/rtc,通过ioctl()设置RTC频率,代码示例如下:
#include <stdio.h>#include <linux/rtc.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>int main(int argc, char* argv[]){unsigned long i = 0;unsigned long data = 0;int retval = 0;int fd = open ("/dev/rtc", O_RDONLY);if(fd < 0){perror("open");exit(errno);}/*Set the freq as 4Hz*/if(ioctl(fd, RTC_IRQP_SET, 1) < 0){perror("ioctl(RTC_IRQP_SET)");close(fd);exit(errno);}/* Enable periodic interrupts */if(ioctl(fd, RTC_PIE_ON, 0) < 0){perror("ioctl(RTC_PIE_ON)");close(fd);exit(errno);}for(i = 0; i < 100; i++){if(read(fd, &data, sizeof(unsigned long)) < 0){perror("read");close(fd);exit(errno);}printf("timer\n");}/* Disable periodic interrupts */ioctl(fd, RTC_PIE_OFF, 0);close(fd);return 0;}
方法三:使用select()
这种方法比较冷门,通过使用select(),来设置定时器;原理利用select()方法的第5个参数,第一个参数设置为0,三个文件描述符集都设置为NULL,第5个参数为时间结构体,代码如下:
#include <sys/time.h>#include <sys/select.h>#include <time.h>#include <stdio.h>/*seconds: the seconds; mseconds: the micro seconds*/void setTimer(int seconds, int mseconds){struct timeval temp;temp.tv_sec = seconds;temp.tv_usec = mseconds;select(0, NULL, NULL, NULL, &temp);printf("timer\n");return ;}int main(){int i;for(i = 0 ; i < 100; i++)setTimer(1, 0);return 0;}
总结:
RTC机制和select()机制精度均能够达到微妙级别。
网上有很多基于select()的多线程定时器,说明select()稳定性还是非常好。
