Linux進程之alarm()信號傳送鬧鐘函數

最近在學習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;
}

alarm()信號傳送鬧鐘函數測試4

程序分析:在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;
}

alarm()信號傳送鬧鐘函數測試5

程序分析:與test4.c文件不一樣的是,在文件test5.c中鬧鐘函數爲alarm(5)。所以,整個程序執行的時間爲5+5=10秒。值得注意的是,alarm(0)表示清除以前設置的鬧鐘信號,並返回0。由於,若是這裏把alarm(5)改爲alarm(0),那麼整個程序執行的時間爲5+0=5秒。

相關文章
相關標籤/搜索