日期:2014-05-16  浏览次数:20600 次

关于linux下的定时函数的一些认识
今天看书看到了关于alarm的一些用法,自己有在网上找了些资料看了下;
1。alarm()执行后,进程将继续执行,在后期(alarm以后)的执行过程中将会在seconds秒后收到信号SIGALRM并执行其处理函数。
C/C++ code

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void sigalrm_fn(int sig)
{
    printf("alarm!\n");
    alarm(2);
    return;
}
int main(void)
{
    signal(SIGALRM, sigalrm_fn);
    alarm(1);
    while(1) pause();
}



2.alarm定时器,但是只能精确到秒,然而我们如果需要用到更精准的怎么办?
经过群里的大牛知道,看了下可以用setitimer
 int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
 setitimer()比alarm功能强大,支持3种类型的定时器:
  ITIMER_REAL : 以系统真实的时间来计算,它送出SIGALRM信号。
  ITIMER_VIRTUAL : -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
  ITIMER_PROF : 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。
  setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例;第三个参数可不做处理。
  setitimer()调用成功返回0,否则返回-1。

  下面是关于setitimer调用的一个简单示范,在该例子中,每隔一秒发出一个SIGALRM,每隔0.5秒发出一个SIGVTALRM信号:
C/C++ code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
int sec;
void sigroutine(int signo){
    switch (signo){
        case SIGALRM:
            printf("Catch a signal -- SIGALRM \n");
            signal(SIGALRM, sigroutine);
            break;
        case SIGVTALRM:
            printf("Catch a signal -- SIGVTALRM \n");
            signal(SIGVTALRM, sigroutine);
            break;
    }
    return;
}
int main()
{
    struct itimerval value, ovalue, value2;          //(1)
    sec = 5;
    printf("process id is %d\n", 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, &ovalue);     //(2)
    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, &ovalue);
    for(;;)
        ;
}


setitimer不会引起线程的阻塞、也不会引起线程的切换动作,就是简单的启动一个定时器,开始定时,而且这种定时应该是基于内核的,(windwos的settimer是基于一种消息的模型);setitimer虽然有三种类型ITIMER_REAL,ITIMER_VIRTUAL ITIMER_PROF,但是在同一时间同一进程,一种类型的只能有1个setitimer;
如果我们需要多个定时器怎么办?
3.
Linux下的微秒级定时器: usleep, nanosleep, select, pselect 


C/C++ code

#include<stdio.h>   
#include<stdlib.h>   
#include<time.h>   
#include<sys/time.h>   
#include<errno.h>   
#include<string.h>   
#include<unistd.h>   
#include<sys/types.h>   
#include<sys/select.h>   
  
  
int main(int argc, char **argv)  
{  
    unsigned int nTimeTestSec = 0;  
    unsigned int nTimeTest = 0;  
    struct timeval tvBegin;  
    struct timeval tvNow;  
    int ret = 0;  
    unsigned int nDelay = 0;  
    struct timeval tv;  
    int fd = 1;  
    int i = 0;  
    struct timespec req;  
  
    unsigned int delay[20] =   
        {500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0};  
    int nReduce = 0; //误差   
  
    fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");  
    fprintf(stderr, "----------------------------------------------------\n");  
    for (i = 0; i < 20; i++)  
    {  
        if (delay[i] <= 0)