Linux定时器

Linux定时器

本文为对CSDN博主「songly_」的原创文章整理后著作的,遵循 CC 4.0 BY-SA 版权协议,
原文链接:https://blog.csdn.net/qq_35733751/article/details/82763230

struct:timerval

//itimerval结构体中的成员类型为timeval
struct timeval {
    time_t      tv_sec;         /* 秒 */
    suseconds_t tv_usec;        /* 微秒 */
};

该结构体表示一个计时时间类型,可以存储秒+微妙

struct:itimerval

struct itimerval {
    struct timeval it_interval; 	/* 周期性的定时器 */
    struct timeval it_value;        	/* 一次性定时器 */
};

这个表示一个计时器类型,具体使用情况如下:

  1. setitimer函数来在指定的模式下注册定时器
  2. it_value的值将随着指定模式下的时间的流逝而减少对应的值,当减少到0时,会发出对应的信号,并让it_value的值重置为it_interavl
  3. it_intervalit_value的值同时为0是时,计时器停止(只有初始情况下it_interval的值为0的时候才有可能停止),否则返回第二步。
    • 注:timeval类型的值为0当且仅当其两个成员的值都为0

所以计时器的在不同情况的值下有不同的功能

  • it_interval的值为0,it_value的值不为0时,该计时器表示为一次性计时器,定时时间为it_value
  • it_interval的不值为0,it_value的值为0时,该计时器表示为周期性计时器,周期为it_interval
  • it_interval的不值为0 且 it_value的值不为0时,该计时器首先等待it_value的时间后发出对应的信号,之后变为一个周期为it_interval的定时器。

function:setitimer

函数原型

#include <sys/time.h>
int setitimer(int which , const struct itimerval *new_value , struct itimerval *old_value);

返回值说明:成功返回0;失败则返回-1并设置errno

参数1

在调用setitimer创建定时器时,可通过指定参数which创建以下几种不同的定时器:

ITIMER_REAL:表示以linux系统的真实时间来计时的定时器,每次超时将会产生SIGALRM信号并发送给进程。

ITIMER_VIRTUAL:以进程在用户模式下执行的cpu时间来计时的定时器,每次超时将会产生SIGVTALRM信号并发送给进程

ITIMER_PROF:以进程在用户和内核两种模式下执行的cpu时间总和来计时的定时器,每次超时将会产生SIGPROF信号并发送给进程

参数2,3

参数new_value指定定时器超时时间,参数old_value返回上一次定时器的时间,另外new_valueold_value两个参数的类型都是struct itimerval类型,如果参数old_value不为NULL时,函数会将上次对应模式下的定时器的状态存入old_value

注:需要注意的是,计时器只会在which指定的模式下计时的。

相似的还有更简单的alrm函数

程序示例1:设置一次性定时器

实验以linux系统下的真实时间为例

#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

int main(void)
{	    
        //把time初始化,这一步操作不能少
        struct itimerval time = {0};

        //设置一次性定时器,超时时间为3秒
        time.it_value.tv_usec = 0;
        time.it_value.tv_sec = 3;
        
        //如果不关心上一次定时器的超时时间,old_value可以传NULL
        setitimer(ITIMER_REAL , &time , NULL);
        //每隔1秒打印一次
        while(1){
                puts("hello world");
                sleep(1);
        }

        return 0;
}

输出结果:三行hello world+一行Alarm clock

通过程序执行结果来看,setitimer程序每隔1秒打印一次hello world,当定时器超时后,发送了SIGALRM信号并终止了该进程。

程序实例2:设置周期性定时器
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>

void sig_handler(int signum){
        if(signum == SIGALRM){
                puts("hello SIGALRM");
        }
}

int main(void)
{
        //一定要把time初始化
        struct itimerval time = {0};  

        //设置一次性定时器,超时时间为4秒
        time.it_value.tv_usec = 0;
        time.it_value.tv_sec = 4;

        //设置周期性定时器,超时时间为3秒
        //表示第一次超时为4秒,之后每次超时为3秒
        time.it_interval.tv_sec = 3;
        time.it_interval.tv_usec = 0;

        signal(SIGALRM , sig_handler);

        setitimer(ITIMER_REAL , &time , NULL);

        while(1){
                puts("hello world");
                sleep(1);
        }

        return 0;
}

输出:

程序首先输出了四行hello world和一行hello SIGALRM,之后周期性输出三行hello world和一行hello SIGALRM,直至ctrl+c结束进程。

程序示例3:自定义alarm函数
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>

unsigned int myalarm(unsigned int seconds)
{
    struct itimerval old_time, itime;

    //清空itime,这一步操作一定要做
    memset(&itime , 0 , sizeof(itime));

    itime.it_value.tv_sec = seconds;
    setitimer(ITIMER_REAL,&itime,&old_time);
    //printf("tv_sec=%ld\n",old_time.it_value.tv_sec);
    return old_time.it_value.tv_sec;
}

int main()
{
    unsigned int ret = 0;
    //设置定时器的超时时间为10秒
    ret = myalarm(10);
    printf("old_time = %d\n",ret);
    sleep(3);
    //第二次修改了定时器的超时时间为3秒
    ret = myalarm(3);

    //获取到的上一次定时器时间
    printf("old_time = %d\n",ret);

    while(1){
        printf("hello world\n");
        sleep(1);
    }
    return 0;
}

输出结果:old_time=0\n+old_time=6\n+3行hello world+1行Alarm clock

根据程序执行结果来看,第一设置定时器的超时时间为10秒,定时器开始倒计时(tv_sec的值开始递减),程序休眠3秒后,第二次把定时器的超时时间修改为3秒,按理来说,此时上一次定时器的超时时间应该递减为7秒了,参数old_value获取上一次的定时器超时时间也是7。但程序打印出来的却是6秒,这是因为程序执行需要消耗时间,所以在获取上一次定时器的超时时间是有损耗的,真实时间应该是6秒多。

最后定时器在3秒后超时,向进程发送了SIGALRM信号。

function:getitimer

函数原型:

作用:获取间隔定时器的值

int getitimer(int which, struct itimerval *value);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值