Linux下多定时器的实现

linux下多定时器的实现
一、已有的定时器接口
   时空管理是计算机系统的主要任务。在时间管理中,我们经常利用定时器处理事情:比如tcp协议中利用定时器管理包超时,视频显示中利用定时器来定时显示视频帧,web服务中利用定时器来管理用户的超时。windows系统提供了SetTimer和timeSetEvent等定时器接口,linux中则提供了setitimer等接口。这些函数的接口很类似,大体上都是用户提供回调函数和超时时间向OS注册一个定时器事件,OS在超时时间到了的时候,调用用户提供的回调函数来完成用户想要做的事情。windows下的接口支持单进程中拥有多个定时器,而linux则只允许单进程拥有一个定时器,因此在linux下的单进程中要使用多个定时器,则需要自己维护管理,这是本文写作的出发点。另外,OS提供的定时器管理算法在大规模定时器的管理方面可能还不尽人意,这时候就需要用户去优化管理算法了,本文在这方面提供了一点素材。

二、一个最简单的多定时器的实现(linux版)

1、实现细节
  这个实现允许用户使用多个自定义的定时器,每个自定义的定时器将周期地被触发直到其被删除。实现的主要思路是:
    i)首先在初始化多定时器(init_mul_timer)时利用setitimer注册一个基本的时间单位(如1s)的定时事件;
    ii)用户需要set_a_timer注册
自定义定时器 时,在timer_manage管理结构中记录这个定时器的回调函数和定时周期等参数;
    iii)当基本的时间单位到期后(如SIGALRM信号到达时),遍历整个timer_manage,如果有自定义定时器的超时时间到了,就执行相应的回调函数,并将
自定义定时器 的超时时间置为最初值;否则将 自定义定时器 的超时时间相应地减一个基本的时间单位;
    iv)用户通过del_a_timer来删除某个定时器,通 过destroy_mul_timer来删除整个多定时器。
2、代码
i) mul_timer.h

/* This file provides an interface of multiple timers. for convenience, it simplify signal processing.
 * Also, it can't be used in multithreading environment.
 * Author:bripengandre
 * Date:2009-04-29
 */

#ifndef _MUL_TIMER_H_
#define _MUL_TIMER_H_

#include <sys/time.h>

#define MAX_TIMER_CNT 10
#define MUL_TIMER_RESET_SEC 10
#define TIMER_UNIT 60
#define MAX_FUNC_ARG_LEN 100
#define INVALID_TIMER_HANDLE (-1)

typedef int timer_handle_t;

typedef struct _timer_manage
{
    struct _timer_info
    {
        int state; /* on or off */
        int interval;
        int elapse; /* 0~interval */
        int (* timer_proc) (void *arg, int arg_len);
        char func_arg[MAX_FUNC_ARG_LEN];
        int arg_len;
    }timer_info[MAX_TIMER_CNT];

    void (* old_sigfunc)(int);
    void (* new_sigfunc)(int);
    struct itimerval value, ovalue;
}_timer_manage_t;

/* success, return 0; failed, return -1 */
int init_mul_timer(void);
/* success, return 0; failed, return -1 */
int destroy_mul_timer(void);
/* success, return timer handle(>=0); failed, return -1 */
timer_handle_t set_a_timer(int interval, int (* timer_proc) (void *arg, int arg_len), void *arg, int arg_len);
/* success, return 0; failed, return -1 */
int del_a_timer(timer_handle_t handle);

#endif /* _MUL_TIMER_H_ */

ii)mul_timer.c

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include "mul_timer.h"

static struct _timer_manage timer_manage;

static void sig_func(int signo);

/* success, return 0; failed, return -1 */
int init_mul_timer(void)
{
    int ret;
    
    memset(&timer_manage, 0, sizeof(struct _timer_manage));
    if( (timer_manage.old_sigfunc = signal(SIGALRM, sig_func)) == SIG_ERR)
    {
        return (-1);
    }
    timer_manage.new_sigfunc = sig_func;
    
    timer_manage.value.it_value.tv_sec = MUL_TIMER_RESET_SEC;
    timer_manage.value.it_value.tv_usec = 0;
    timer_manage.value.it_interval.tv_sec = TIMER_UNIT;
    timer_manage.value.it_interval.tv_usec = 0;
    ret = setitimer(ITIMER_REAL, &timer_manage.value, &timer_manage.ovalue);
    
    return (ret);
}


/* success, return 0; failed, return -1 */
int destroy_mul_timer(void)
{
    int ret;
    
    if( (signal(SIGALRM, timer_manage.old_sigfunc)) == SIG_ERR)
    {
        return (-1);


    }

    ret = setitimer(ITIMER_REAL, &timer_manage.ovalue, &timer_manage.value);
    if(ret < 0)
    {
        return (-1);
    }
    memset(&timer_manage, 0, sizeof(struct _timer_manage));
    
    return(0);
}


/* success, return timer handle(>=0); failed, return -1 */
timer_handle_t set_a_timer(int interval, int (* timer_proc) (void *arg, int arg_len), void *arg, int arg_len)
{
    int i;
    
    if(timer_proc == NULL || interval <= 0)
    {
        return (-1);
    }
    
    for(i = 0; i < MAX_TIMER_CNT; i++)
    {
        if(timer_manage.timer_info[i].state == 1)
        {
            continue;
        }
        
        memset(&timer_manage.timer_info[i], 0, sizeof(timer_manage.timer_info[i]));
        timer_manage.timer_info[i].timer_proc = timer_proc;
        if(arg != NULL)
        {
            if(arg_len > MAX_FUNC_ARG_LEN)
            {
                return (-1);
            }
            memcpy(timer_manage.timer_info[i].func_arg, arg, arg_len);
            timer_manage.timer_info[i].arg_len = arg_len;
        }
        timer_manage.timer_info[i].interval = interval;
        timer_manage.timer_info[i].elapse

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Linux中,有几种方法可以实现定时器功能: 1. 使用系统调用 alarm():该调用会在指定的时间(以秒为单位)后触发SIGALRM信号。可以通过注册信号处理函数来处理该信号,实现定时器功能。例如: ``` #include <unistd.h> #include <signal.h> void handler(int signum) { // 定时器触发后的处理逻辑 } int main() { signal(SIGALRM, handler); alarm(5); // 5秒后触发SIGALRM信号 while (1) {} // 持续运行程序,直到收到SIGALRM信号 return 0; } ``` 2. 使用timer_create()函数:该函数可以创建一个定时器,精度可以达到毫秒级别。例如: ``` #include <time.h> #include <signal.h> void handler(int signum) { // 定时器触发后的处理逻辑 } int main() { struct sigevent sev; timer_t timerid; struct itimerspec its; // 创建定时器 sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGUSR1; sev.sigev_value.sival_ptr = &timerid; timer_create(CLOCK_REALTIME, &sev, &timerid); // 设置定时器 its.it_value.tv_sec = 1; its.it_value.tv_nsec = 0; its.it_interval.tv_sec = 1; its.it_interval.tv_nsec = 0; timer_settime(timerid, 0, &its, NULL); // 注册信号处理函数 signal(SIGUSR1, handler); while (1) {} // 持续运行程序,直到收到SIGUSR1信号 return 0; } ``` 3. 使用select()函数:该函数可以等待多个文件描述符中的任意一个就绪,可以通过设置超时时间实现定时器功能。例如: ``` #include <stdio.h> #include <sys/select.h> int main() { fd_set rfds; struct timeval tv; while (1) { // 清空文件描述符集合 FD_ZERO(&rfds); // 设置需要监视的文件描述符 FD_SET(0, &rfds); // 监视标准输入 // 设置超时时间 tv.tv_sec = 5; tv.tv_usec = 0; // 等待文件描述符就绪或超时 int ret = select(1, &rfds, NULL, NULL, &tv); if (ret == -1) { perror("select"); } else if (ret == 0) { printf("Timeout\n"); // 超时处理逻辑 } else { if (FD_ISSET(0, &rfds)) { printf("Input available\n"); // 文件描述符就绪处理逻辑 } } } return 0; } ``` 这些方法都可以实现定时器功能,选择哪种方法取决于具体的场景和需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值