基于setitimer实现允许单进程多次调用的定时器

本文介绍了如何通过setitimer在Linux环境中创建一个可以在进程中多次调用的定时器。通过链表管理定时事件,当计时到达后恢复节点初始时间以实现重复计时。文章还讨论了可能的优化方案,包括不依赖信号、采用更高效的数据结构(如最小堆)以及改进计时原理,引入时间轮概念。
摘要由CSDN通过智能技术生成

原理

setitimer不能在进程中多次调用,考虑用链表管理调用。每个节点包含当前事件还剩余多少时间,回调等,每次有新节点时,重新更新节点时间。在计数到来后,重新恢复节点初始时间实现重复计时,删除相对简单,挪掉节点即可。

函数原型

int set_timer(struct own_timer **t, struct timeval val, callback* cb, void* arg) ;
int free_timer(struct own_timer* timer) ;

源码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>


#define MIN(a,b) (((a) < (b))?(a):(b))




typedef void (*callback)(void* argc);

typedef struct list {
    void* next;
    void* prev;
} LIST_ENTRY;

struct own_timer {
    LIST_ENTRY entry;
    int handle;
    struct timeval left_dyn;
    struct timeval left_init;
    callback* cb;
    void* cb_arg;
};

static LIST_ENTRY *head = NULL;
static LIST_ENTRY *tail = NULL;
static struct timeval last_set;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int test = 0;

static struct own_timer *t1 = NULL;
static struct own_timer *t2 = NULL;
static struct own_timer *t3 = NULL;


void timeout(void* arg)
{
    printf("timeout %d >>\n",(int)arg);
}

void timeout4(void* arg)
{
    printf("timeout4 >>>>>>>>>\n");
    test ++;
}

static int compare_time(struct timeval a, struct timeval b)
{
    if(a.tv_sec > b.tv_sec)
        return 1;
    else if(a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec) 
        return 1;
    else if(a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec) 
        return 0;
    else
        return -1;
}

static int diff_time(struct timeval* result, struct timeval* old,struct  timeval* newt)
{
    if(compare_time(*old,*newt) < 0) {
        //printf("old shoud bigger\n");
        return -
要启动多个定时器,可以使用 `setitimer` 函数实现。`setitimer` 函数可以设置一个或多个定时器,用于在指定的时间间隔内触发信号。 下面是一个示例代码,演示如何启动多个定时器: ```c #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h> void timer_handler(int signum) { printf("Timer expired!\n"); } int main() { struct itimerval timer1, timer2; // 设置第一个定时器 timer1.it_value.tv_sec = 1; // 第一次触发的时间间隔为1秒 timer1.it_value.tv_usec = 0; timer1.it_interval.tv_sec = 2; // 之后每次触发的时间间隔为2秒 timer1.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &timer1, NULL); // 使用实时时间 // 设置第二个定时器 timer2.it_value.tv_sec = 5; // 第一次触发的时间间隔为5秒 timer2.it_value.tv_usec = 0; timer2.it_interval.tv_sec = 5; // 之后每次触发的时间间隔为5秒 timer2.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &timer2, NULL); // 注册信号处理函数 signal(SIGALRM, timer_handler); // 等待定时器触发 while (1) { // 进行其他操作 } return 0; } ``` 在上述示例中,我们使用了两个不同的 `itimerval` 结构体变量 `timer1` 和 `timer2` 来分别设置两个定时器。然后使用 `setitimer` 函数将这两个定时器设置为实时计时器,并指定了对应的时间间隔。之后,我们注册了信号处理函数 `timer_handler` 来处理定时器触发的信号 `SIGALRM`。 最后,在主函数中使用一个无限循环来等待定时器的触发,可以在循环中进行其他操作。 希望这个示例能帮助到你!如有任何问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值