1. 程式人生 > >SIGALRM信號和SIGCHID信號

SIGALRM信號和SIGCHID信號

可執行 信號處理函數 進程 操作 nal lrm pro print setbuf

在進行堵塞式系統調用時。為避免進程陷入無限期的等待,能夠為這些堵塞式系統調用設置定時器。Linux提供了alarm系統調用和SIGALRM信號實現這個功能。

要使用定時器。首先要安裝SIGALRM信號。假設不安裝SIGALRM信號,則進程收到SIGALRM信號後。缺省的動作就是終止當前進程。

SIGALRM信號成功安裝後,在什麽情況下進程會收到該信號呢?這就要依賴於Linux提供的定時器功能。在Linux系統下,每一個進程都有惟一的一個定時器,該定時器提供了以秒為單位的定時功能。在定時器設置的超時時間到達後,調用alarm的進程將收到SIGALRM信號。

alarm系統調用的原型為:

#include <unistd.h>
unsigned int alarm(unsigned int seconds); 參數說明: 1)seconds:要設定的定時時間,以秒為單位。在alarm調用成功後開始計時。超過該時間將觸發SIGALRM信號。 返回值: 返回當前進程曾經設置的定時器剩余秒數。 例8-10:編程利用SIGALRM信號實現秒定時器。 代碼例如以下: #include <stdio.h> #include <signal.h> //全局計數器變量 int Cnt=0; //SIGALRM信號處理函數 void CbSigAlrm(int signo) { //輸出定時提示信息
printf(" seconds: %d",++Cnt); printf("\r"); //又一次啟動定時器,實現1秒定時 alarm(1); } void main() { //安裝SIGALRM信號 if(signal(SIGALRM,CbSigAlrm)==SIG_ERR) { perror("signal"); return; } //關閉標準輸出的行緩存模式 setbuf(stdout,NULL); //啟動定時器 alarm(1); //進程進入無限循環,僅僅能手動終止 while(1) { //暫停,等待信號 pause(); } } 8.5.2 SIGCLD信號
在Linux的多進程編程中,SIGCLD是一個很重要的信號。當一個子進程退出時。並非馬上釋放其占用的資源,而是通知其父進程,由父進程進行興許的工作。

在這一過程中,系統將依次產生下列事件。

1)向父進程發送SIGCLD信號,子進程進入zombie(僵屍)狀態。 2)父進程接收到SIGCLD信號,進行處理。 假設在上述過程中父進程既沒有忽略SIGCLD信號。也未捕獲該信號進行處理,則子進程將進入僵屍狀態。僵屍狀態的進程不能被操作系統調用,也沒有不論什麽可執行代碼,它只是是占用了進程列表中的一個位置而已。

假設僅有幾個僵屍進程不會影響系統的執行,可是假設僵屍進程過多。則將會嚴重影響系統的執行。因此,在編程過程中應避免產生僵屍進程。有兩種主要的處理方法能夠避免產生僵屍進程:一是父進程忽略SIGCLD信號;二是父進程捕獲SIGCLD信號,在信號處理函數中獲取子進程的退出狀態。忽略信號的方式比較簡單。僅僅須要調用signal(SIGCLD,SIG_IGN)語句就可以完畢。假設要捕獲信號並處理。那麽先要安裝SIGCLD信號,然後在信號處理函數中調用wait或者waitpid等函數獲取子進程的退出狀態。

例8-11:編程捕獲SIGCLD信號。輸出各子進程的ID和退出狀態碼。 代碼例如以下: #include <stdio.h> #include <stdlib.h> #include <signal.h> //SIGCLD信號處理函數 void CbSigCld(int signo) { //保存退出進程的ID int pid; //保存退出進程的退出狀態碼 int status; //等待不論什麽一個子進程退出 pid=waitpid(-1,&status,0); //輸出退出的子進程ID和退出代碼 printf("Child process %d exit with status %d\n",pid,status); } void main() { int i,pid; //安裝SIGCLD信號 if(signal(SIGCLD,CbSigCld)==SIG_ERR) { perror("signal"); return; } //循環創建子進程 for(i=0;i<5;i++) { pid=fork(); //假設是子進程 if(pid==0) { //退出子進程,退出狀態碼為0 exit(0); } //假設是父進程 else { sleep(1); } } }

SIGALRM信號和SIGCHID信號