zoukankan      html  css  js  c++  java
  • linux系统编程之信号(八):三种时间结构及定时器setitimer()详解

    一,三种时间结构

    time_t://seconds

    struct timeval {

    long tv_sec; /* seconds */

    long tv_usec; /* microseconds */

    };

    struct timespec {

    time_t tv_sec; /* seconds */

    long tv_nsec; /* nanoseconds */

    };

    二,setitimer()

    现在的系统中很多程序不再使用alarm调用,而是使用setitimer调用来设置定时器,用getitimer来得到定时器的状态,

    这两个调用的声明格式如下:

    #include <sys/time.h>

    int getitimer(int which, struct itimerval *curr_value);
    int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);

    参数:

    • 第一个参数which指定定时器类型
    • 第二个参数是结构itimerval的一个实例,结构itimerval形式
    • 第三个参数可不做处理。

    返回值:成功返回0失败返回-1

    该系统调用给进程提供了三个定时器,它们各自有其独有的计时域,当其中任何一个到达,就发送一个相应的信号给进程,并使得计时器重新开始。三个计时器由参数which指定,如下所示:

    TIMER_REAL:按实际时间计时,计时到达将给进程发送SIGALRM信号。

    ITIMER_VIRTUAL:仅当进程执行时才进行计时。计时到达将发送SIGVTALRM信号给进程。

    ITIMER_PROF:当进程执行时和系统为该进程执行动作时都计时。与ITIMER_VIR-TUAL是一对,该定时器经常用来统计进程在用户态和内核态花费的时间。计时到达将发送SIGPROF信号给进程。

    定时器中的参数value用来指明定时器的时间,其结构如下:

    struct itimerval {

            struct timeval it_interval; /* 第一次之后每隔多长时间 */

            struct timeval it_value; /* 第一次调用要多长时间 */

    };

    该结构中timeval结构定义如下:

    struct timeval {

            long tv_sec; /* 秒 */

            long tv_usec; /* 微秒,1秒 = 1000000 微秒*/

    };

    在setitimer 调用中,参数ovalue如果不为空,则其中保留的是上次调用设定的值。定时器将it_value递减到0时,产生一个信号,并将it_value的值设定为it_interval的值,然后重新开始计时,如此往复。当it_value设定为0时,计时器停止,或者当它计时到期,而it_interval 为0时停止。调用成功时,返回0;错误时,返回-1,并设置相应的错误代码errno:

    EFAULT:参数value或ovalue是无效的指针。

    EINVAL:参数which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一个。

    示例一:

    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/time.h>
    
    
    #define ERR_EXIT(m) 
        do 
        { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)
    
    void handler(int sig)
    {
        printf("recv a sig=%d
    ", sig);
    }
    
    int main(int argc, char *argv[])
    {
        if (signal(SIGALRM, handler) == SIG_ERR)
            ERR_EXIT("signal error");
    
        struct timeval tv_interval = {1, 0};
        struct timeval tv_value = {5, 0};
        struct itimerval it;
        it.it_interval = tv_interval;
        it.it_value = tv_value;
        setitimer(ITIMER_REAL, &it, NULL);
    
        for (;;)
            pause();
        return 0;
    }

    结果:

    QQ截图20130715202529

    可以看到第一次发送信号是在5s以后,之后每隔一秒发送一次信号

    示例二:获得产生时钟信号的剩余时间

    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/time.h>
    
    
    #define ERR_EXIT(m) 
        do 
        { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)
    
    
    int main(int argc, char *argv[])
    {
        struct timeval tv_interval = {1, 0};
        struct timeval tv_value = {1, 0};
        struct itimerval it;
        it.it_interval = tv_interval;
        it.it_value = tv_value;
        setitimer(ITIMER_REAL, &it, NULL);
    
        int i;
        for (i=0; i<10000; i++);
    
    //第一种方式获得剩余时间
        struct itimerval oit;
        setitimer(ITIMER_REAL, &it, &oit);//利用oit获得剩余时间产生时钟信号
        printf("%d %d %d %d
    ", (int)oit.it_interval.tv_sec, (int)oit.it_interval.tv_usec, (int)oit.it_value.tv_sec, (int)oit.it_value.tv_usec);
    //第二种方式获得剩余时间
        //getitimer(ITIMER_REAL, &it);
        //printf("%d %d %d %d
    ", (int)it.it_interval.tv_sec, (int)it.it_interval.tv_usec, (int)it.it_value.tv_sec, (int)it.it_value.tv_usec);
    
        return 0;
    }

    结果:

    用第一种方式:

    QQ截图20130715204042

    用第二种方式:利用getitimer在不重新设置时钟的情况下获取剩余时间

    QQ截图20130715204130

    剩余时间是指:距离下一次调用定时器产生信号所需时间,这里由于for循环不到一秒就执行完,定时器还来不及产生时钟信号,所以有剩余时间

    示例三:每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号

    #include <signal.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <sys/time.h>
    
    void sigroutine(int signo)
    {
            switch (signo) {
            case SIGALRM:
            printf("Catch a signal -- SIGALRM
     ");
            break;
            case SIGVTALRM:
            printf("Catch a signal -- SIGVTALRM
     ");
            break;
            }
            return;
    }
    
    int main()
    {
    
           struct itimerval value,value2;
            printf("process id is %d
     ",getpid());
    
            signal(SIGALRM, sigroutine);
    
            signal(SIGVTALRM, sigroutine);
    
            value.it_value.tv_sec = 1;
    
            value.it_value.tv_usec = 0;
    
            value.it_interval.tv_sec = 1;
    
            value.it_interval.tv_usec = 0;
    
            setitimer(ITIMER_REAL, &value,NULL);
    
    
            value2.it_value.tv_sec = 0;
    
            value2.it_value.tv_usec = 500000;
    
            value2.it_interval.tv_sec = 0;
    
            value2.it_interval.tv_usec = 500000;
    
            setitimer(ITIMER_VIRTUAL, &value2,NULL);
    
            for (;;) ;
    
    }

    结果:

    QQ截图20130715205534

    可知确实是没两次SIGVTALRM一次SIGALRM

  • 相关阅读:
    KnockoutJS 3.X API 第五章 高级应用(4) 自定义处理逻辑
    KnockoutJS 3.X API 第五章 高级应用(3) 虚拟元素绑定
    KnockoutJS 3.X API 第五章 高级应用(2) 控制后代绑定
    KnockoutJS 3.X API 第五章 高级应用(1) 创建自定义绑定
    KnockoutJS 3.X API 第四章(14) 绑定语法细节
    KnockoutJS 3.X API 第四章(13) template绑定
    KnockoutJS 3.X API 第四章 表单绑定(12) selectedOptions、uniqueName绑定
    KnockoutJS 3.X API 第四章 表单绑定(11) options绑定
    KnockoutJS 3.X API 第四章 表单绑定(10) textInput、hasFocus、checked绑定
    KnockoutJS 3.X API 第四章 表单绑定(9) value绑定
  • 原文地址:https://www.cnblogs.com/mickole/p/3191977.html
Copyright © 2011-2022 走看看