最近在学习Linux系统编程遇到了一个颇有意思的函数:alarm(),它是一个用来设置信号传送的闹钟函数。网上找了一些资料,结合本身的学习体会,如今Mark一下。编程
1 alarm()函数说明函数
[1] 引用头文件:#include <unistd.h>; [2] 函数标准式:unsigned int alarm(unsigned int seconds); [3] 功能与做用:alarm()函数的主要功能是设置信号传送闹钟,即用来设置信号SIGALRM在通过参数seconds秒数后发送给目前的进程。若是未设置信号SIGALARM的处理函数,那么alarm()默认处理终止进程。 [4] 函数返回值:若是在seconds秒内再次调用了alarm函数设置了新的闹钟,则后面定时器的设置将覆盖前面的设置,即以前设置的秒数被新的闹钟时间取代;当参数seconds为0时,以前设置的定时器闹钟将被取消,并将剩下的时间返回。
2 alarm()闹钟函数的测试学习
了解了alarm()函数的功能特性和返回值的特性后,咱们就能够对其测试。测试方向有两个:其一,测试常规只单独存在一个闹钟函数alarm()的程序;其二,测试程序中包含多个alarm()闹钟函数。所以整理了下面几个程序,经过比较学习更有助于理解。测试环境是RedHat Linux5.3,GCC编译调试。测试
2.1 alarm()测试1.1调试
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> void sig_alarm() { exit(0); } int main(int argc, char *argv[]) { signal(SIGALRM, sig_alarm); alarm(10); sleep(15); printf("Hello World!\n"); return 0; }
[root@localhost wk]# gcc test1.c -o test1 [root@localhost wk]# ./test1 [root@localhost wk]#
程序分析:在文件test1.c中,定义了一个时钟alarm(10),它的做用是让信号SIGALRM在通过10秒后传送给目前main()所在进程;接着又定义了sleep(15),它的做用是让执行挂起15秒的时间。因此当main()程序挂起10秒钟时,signal函数调用SIGALRM信号的处理函数sig_alarm,而且sig_alarm执行exit(0)使得程序直接退出。所以,printf("Hello World!\n")语句是没有被执行的。code
2.2 alarm()测试1.2blog
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> void sig_alarm() { exit(0); } int main(int argc, char *argv[]) { signal(SIGALRM, sig_alarm); alarm(10); sleep(5); printf("Hello World!\n"); return 0; }
[root@localhost wk]# gcc test2.c -o test2 [root@localhost wk]# ./test2 Hello World!
程序分析:与test1.c文件不一样的是,在文件test2.c中延时函数为sleep(5),即执行挂起5秒的时间。因此当main()程序挂起5秒钟时,因为还没到达设置的闹钟10秒,那么main就执行下面的printf("Hello World!\n")语句;紧接着又执行下面的return 0语句,从而直接退出程序。所以,整个test2.c文件输出的内容为:Hello World!。进程
2.3 alarm()测试2it
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> void handler() { printf("hello\n"); } void main() { int i; signal(SIGALRM, handler); alarm(5); for(i = 1; i < 7; i++) { printf("sleep %d ...\n", i); sleep(1); } }
[root@localhost wk]# ./test3 sleep 1 ... sleep 2 ... sleep 3 ... sleep 4 ... sleep 5 ... hello sleep 6 ...
程序分析:在文件test3.c中,定义时钟alarm(5),而main()函数中主要是一个for循环输出语句。当main函数执行到i=5时,for循环先执行printf("sleep %d ...\n", 5)语句输出"sleep 5 ...",而后执行sleep(1)语句。此时已经到达闹钟时间5秒,所以会把信号SIGALRM传送给当前main()函数进程;接着调用SIGALRM信号的处理函数handler,从而输出"hello",而后又返回到sleep(1)这个点;最后for循环执行i=6,输出"sleep 6",最终延时1秒后结束整个程序。io
以上三个程序都只包含一个alarm()闹钟函数,下面两个程序包含两个alarm()。而且为了更为真切的观察包含alarm()闹钟函数的程序的执行过程,程序经过调用系统打印输出当前时间,经过时间差来进一步理解。
2.4 alarm()测试3.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> static void sig_alrm(int signo); int main(void) { signal(SIGALRM,sig_alrm); system("date"); alarm(20); sleep(5); printf("%d\n",alarm(15)); pause(); } static void sig_alrm(int signo){ system("date"); return; } |
程序分析:在test4.c的main()函数中,先设置了一个闹钟函数alarm(20),即在20秒时将SIGALRM信号传送送给当前进程;而后又定义了一个延时函数sleep(5),接着又定义了一个闹钟函数alarm(15),它的做用是清除前面设置的闹钟alarm(20)并返回剩余的时间20-5=15秒。因此,程序先执行system("date")语句输出当前时间;而后进程休眠5秒后,程序执行输出语句printf("%d\n",alarm(15)),因为alarm(15)先返回15秒,即打印输出15;接着程序执行pause()函数,使当前进程处于挂起状态,直到捕捉到一个信号;当再过15秒后,SIGALARM信号的处理函数sig_alrm执行system("date")语句输出当前时间;最后pause终止进程。所以,整个程序执行的时间为5+15=20秒。
2.5 alarm()测试3.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> static void sig_alrm(int signo); int main(void) { signal(SIGALRM,sig_alrm); system("date"); alarm(20); sleep(5); printf("%d\n",alarm(5)); pause(); } static void sig_alrm(int signo){ system("date"); return; } |
程序分析:与test4.c文件不一样的是,在文件test5.c中闹钟函数为alarm(5)。所以,整个程序执行的时间为5+5=10秒。值得注意的是,alarm(0)
表示清除以前设置的闹钟信号,并返回0。由于,若是这里把alarm(5)改为alarm(0),那么整个程序执行的时间为5+0=5秒。