1. alarm函數
[cpp] view plain copy
- [1] 引用頭檔案:#include <unistd.h>;
- [2] 函數标準式:unsigned int alarm(unsigned int seconds);
- [3] 功能與作用:alarm()函數的主要功能是設定信号傳送鬧鐘,即用來設定信号SIGALRM在經過參數seconds秒數後發送給目前的程序。如果未設定信号SIGALARM的處理函數,那麼alarm()預設處理終止程序。
- [4] 函數傳回值:如果在seconds秒内再次調用了alarm函數設定了新的鬧鐘,則後面定時器的設定将覆寫前面的設定,即之前設定的秒數被新的鬧鐘時間取代;當參數seconds為0時,之前設定的定時器鬧鐘将被取消,并将剩下的時間傳回。
2. 測試
原文的測試環境是RedHat Linux5.3,本人在Ubuntu 14.04中再次進行了測試。測試結果與原作者一緻。
了解了alarm()函數的功能特性和傳回值的特性後,我們就可以對其測試。測試方向有兩個:其一,測試正常隻單獨存在一個鬧鐘函數alarm()的程式;其二,測試程式中包含多個alarm()鬧鐘函數。是以整理了下面幾個程式,通過比較學習更有助于了解。測試環境是RedHat Linux5.3,GCC編譯調試。
2.1 alarm()測試1.1
[cpp] view plain copy
- #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;
- }

程式分析:在檔案test1.c中,定義了一個時鐘alarm(10),它的作用是讓信号SIGALRM在經過10秒後傳送給目前main()所在程序;接着又定義了sleep(15),它的作用是讓執行挂起15秒的時間。是以當main()程式挂起10秒鐘時,signal函數調用SIGALRM信号的處理函數sig_alarm,并且sig_alarm執行exit(0)使得程式直接退出。是以,printf("Hello World!\n")語句是沒有被執行的。
2.2 alarm()測試1.2
[cpp] view plain copy
- #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;
- }
程式分析:與test1.c檔案不同的是,在檔案test2.c中延時函數為sleep(5),即執行挂起5秒的時間。是以當main()程式挂起5秒鐘時,由于還沒到達設定的鬧鐘10秒,那麼main就執行下面的printf("Hello World!\n")語句;緊接着又執行下面的return 0語句,進而直接退出程式。是以,整個test2.c檔案輸出的内容為:Hello World!。
2.3 alarm()測試2
[cpp] view plain copy
- #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);
- }
- }
程式分析:在檔案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秒後結束整個程式。
以上三個程式都隻包含一個alarm()鬧鐘函數,下面兩個程式包含兩個alarm()。并且為了更為真切的觀察包含alarm()鬧鐘函數的程式的執行過程,程式通過調用系統列印輸出目前時間,通過時間差來進一步了解。
2.4 alarm()測試3.1
[cpp] view plain copy
- #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
[cpp] view plain copy
- #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秒。
最後:需要注意的是,原作者在文章中進行了精确的時間計算,而程式運作的結果也與作者的計算一緻,但即使如此,精确的結果也是不可信的和計算精确的結果也是不可行的。在某些條件下,我們實際花費和等待的時間很有可能比程式設定的時間要長,而且1秒對于現代的作業系統來說,實在是太長了。
原文連結:https://blog.csdn.net/u010155023/article/details/51984602