最近在學習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秒。