参考:
https://www.cnblogs.com/wenqiang/p/5525261.html
windows下的接口支持单进程中拥有多个定时器,而linux则只允许单进程拥有一个定时器,因此在linux下的单进程中要使用多个定时器,则需要自己维护管理,
1.alarm函数,对定时要求不太精确的话,使用alarm()和signal()就行了
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
void func()
{
printf("this is func\n");
}
int main()
{
signal(SIGALRM, func); //执行的函数
alarm(1);//设置定时1s
while (1);
return 0;
}
上面函数只执行一次,如果想连续执行,需要在func函数中添加 alarm(1);
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
void func()
{
printf("this is func\n");
signal(SIGALRM, func); //1s后要执行的函数
alarm(1);//设置定时1s
}
int main()
{
signal(SIGALRM, func); //1s后要执行的函数
alarm(1);//设置定时1s
while (1);
return 0;
}
2.实现精度较高的定时功能的话,就要使用setitimer函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
void test_func()
{
static count = 0;
printf("count is %d\n", count++);
}
void init_sigaction()
{
struct sigaction act;
act.sa_handler = test_func; //设置处理信号的函数
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGPROF, &act, NULL);//时间到发送SIGROF信号
}
void init_time()
{
struct itimerval val;
val.it_value.tv_sec = 3; //3秒后启用定时器 秒
val.it_value.tv_usec = 0; // 微妙
val.it_interval.tv_sec=3;//定时器间隔为3s
val.it_interval.tv_usec = 0; //
/*如果it_interval设置为0则定时器只执行一次
* val.it_interval.tv_sec=0
*;val.it_interval.tv_sec=0
*/
setitimer(ITIMER_PROF, &val, NULL);
}
int main(int argc, char **argv)
{
init_sigaction();
init_time();
while(1);
return 0;
}
3.基于时间轮的定时器简单实现,在实际项目中,一个常用的做法是新起一个线程,专门管理定时器,定时来源使用rtc、select等比较精确的来源,定时器超时后向主要的work线程发消息即可,或者使用timefd接口
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#define TIME_WHEEL_SIZE 8
typedef void (*func)(int data);
struct timer_node {
struct timer_node *next;
int rotation;
func proc;
int data;
};
struct timer_wheel {
struct timer_node *slot[TIME_WHEEL_SIZE];
int current;
};
struct timer_wheel timer = {{0}, 0};
void tick(int signo)
{
// 使用二级指针删进行单链表的删除
struct timer_node **cur = &timer.slot[timer.current];
while (*cur) {
struct timer_node *curr = *cur;
if (curr->rotation > 0) {
curr->rotation--;
cur = &curr->next;
} else {
curr->proc(curr->data);
*cur = curr->next;
free(curr);
}
}
timer.current = (timer.current + 1) % TIME_WHEEL_SIZE;
alarm(1);
}
void add_timer(int len, func action)
{
int pos = (len + timer.current) % TIME_WHEEL_SIZE;
struct timer_node *node = malloc(sizeof(struct timer_node));
// 插入到对应格子的链表头部即可, O(1)复杂度
node->next = timer.slot[pos];
timer.slot[pos] = node;
node->rotation = len / TIME_WHEEL_SIZE;
node->data = 0;
node->proc = action;
}
// test case1: 1s循环定时器
int g_sec = 0;
void do_time1(int data)
{
printf("timer %s, %d\n", __FUNCTION__, g_sec++);
add_timer(1, do_time1);
}
// test case2: 2s单次定时器
void do_time2(int data)
{
printf("timer %s\n", __FUNCTION__);
}
// test case3: 9s循环定时器
void do_time9(int data)
{
printf("timer %s\n", __FUNCTION__);
add_timer(9, do_time9);
}
int main()
{
signal(SIGALRM, tick);
alarm(1); // 1s的周期心跳
// test
add_timer(1, do_time1);
add_timer(2, do_time2);
add_timer(9, do_time9);
while(1) pause();
return 0;
}