Linux下定时器的设置

1. alarm函数


[1] 引用头文件:#include <unistd.h>;
 
[2] 函数标准式:unsigned int alarm(unsigned int seconds);
 
[3] 功能与作用:alarm()函数的主要功能是设置信号传送闹钟,即用来设置信号SIGALRM在经过参数seconds秒数后发送给目前的进程。如果未设置信号SIGALARM的处理函数,那么alarm()默认处理终止进程。
 
[4] 函数返回值:
    成功:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。注意,alarm调用前就已经返回了。
    出错:-1

2. 测试

测试环境是Centos7。

了解了alarm()函数的功能特性和返回值的特性后,我们就可以对其测试。测试方向有两个:其一,测试常规只单独存在一个闹钟函数alarm()的程序;其二,测试程序中包含多个alarm()闹钟函数。因此整理了下面几个程序,通过比较学习更有助于理解。测试环境是RedHat Linux5.3,GCC编译调试。

2.1 alarm()测试1.1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void handler(int sig) {
    printf("this is handler function!\n");
    exit(0);
}

int main(int argc, char **argv) {
    signal(SIGALRM, handler);
    alarm(1);
    sleep(5);
    printf("hello world!\n");
    return 0;
}

  

程序分析:在文件alarm_test_1.c中,定义了一个时钟alarm(5),它的作用是让信号SIGALRM在经过5秒后传送给目前main()所在进程;接着又定义了sleep(1),它的作用是让执行挂起1秒的时间。所以当main()程序挂起1秒钟时,signal函数调用SIGALRM信号的处理函数sig_alarm,并且sig_alarm输出并执行exit(0)使得程序直接退出。因此,printf("hello world!\n")语句是没有被执行的。

2.2 alarm()测试1.2

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void handler(int sig) {
    printf("this is handler function!\n");
    exit(0);
}

int main(int argc, char **argv) {
    signal(SIGALRM, handler);
    alarm(5);
    sleep(1);
    printf("hello world!\n");
    return 0;
}

  

程序分析:与上一个测试不同的是,在本测试代码中延时函数为sleep(1),即执行挂起5秒的时间。所以当main()程序挂起1秒钟时,由于还没到达设置的闹钟5秒,那么main就执行下面的printf("hello world!\n")语句;紧接着又执行下面的return 0语句,从而直接退出程序。因此,本次输出的内容为:hello world!。

2.3 alarm()测试2

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
    printf("hello, this is signal %d\n", sig);
}

int main(int argc, char **argv) {
    signal(SIGALRM, handler);
    alarm(5);
    for (int i = 1; i < 7; ++i) {
        sleep(1);
        printf("sleep %d secs.\n", i);
    }
    return 0;    
}

  

程序分析:在文件alarm_test_2.cpp中,定义时钟alarm(5),而main()函数中主要是一个for循环输出语句。当main函数执行到i=5时,for循环先执行sleep(1)语句,此时已经到达闹钟时间5秒,因此会把信号SIGALRM传送给当前main()函数进程;接着调用SIGALRM信号的处理函数handler,从而输出"hello",然后for循环中输出这个点printf("sleep %d secs.\n", i)语句输出"sleep 5 ...";最后for循环执行i=6,输出"sleep 6",最终结束整个程序。

以上三个程序都只包含一个alarm()闹钟函数,下面两个程序包含两个alarm()。并且为了更为真切的观察包含alarm()闹钟函数的程序的执行过程,程序通过调用系统打印输出当前时间,通过时间差来进一步理解。

2.4 alarm()测试3.1

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
    system("date");
    return;
}

int main(int argc, char **argv) {
    signal(SIGALRM, handler);
    system("date");
    alarm(10);
    sleep(5);
    printf("%d\n", alarm(1));
    pause();
    return 0;
}
 

程序分析:在alarm_test_3.cpp的main()函数中,先设置了一个闹钟函数alarm(10),即在10秒时将SIGALRM信号传送送给当前进程;然后又定义了一个延时函数sleep(5),接着又定义了一个闹钟函数alarm(1),它的作用是清除前面设置的闹钟alarm(10)并返回剩余的时间10-5=5秒。所以,程序先执行system("date")语句输出当前时间;然后进程休眠5秒后,程序执行输出语句printf("%d\n",alarm(1)),由于alarm(1)先返回5秒,即打印输出5;接着程序执行pause()函数,使当前进程处于挂起状态,直到捕捉到一个信号;当再过1秒后,SIGALARM信号的处理函数sig_alrm执行system("date")语句输出当前时间;最后pause终止进程。因此,整个程序执行的时间为5+1=6秒。

最后:需要注意的是,原作者在文章中进行了精确的时间计算,而程序运行的结果也与作者的计算一致,但即使如此,计算的结果也是不可信的和计算精确的结果也是不可行的。在某些条件下,我们实际花费和等待的时间很有可能比程序设定的时间要长,而且1秒对于现代的操作系统来说,实在是太长了。

猜你喜欢

转载自blog.csdn.net/vanturman/article/details/84131324