linux 定时器

参考:

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;
}
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值