SIGALRM信號和SIGCHID信號
阿新 • • 發佈:2018-02-14
可執行 信號處理函數 進程 操作 nal lrm pro print setbuf
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是一個很重要的信號。當一個子進程退出時。並非馬上釋放其占用的資源,而是通知其父進程,由父進程進行興許的工作。
在進行堵塞式系統調用時。為避免進程陷入無限期的等待,能夠為這些堵塞式系統調用設置定時器。Linux提供了alarm系統調用和SIGALRM信號實現這個功能。
要使用定時器。首先要安裝SIGALRM信號。假設不安裝SIGALRM信號,則進程收到SIGALRM信號後。缺省的動作就是終止當前進程。SIGALRM信號成功安裝後,在什麽情況下進程會收到該信號呢?這就要依賴於Linux提供的定時器功能。在Linux系統下,每一個進程都有惟一的一個定時器,該定時器提供了以秒為單位的定時功能。在定時器設置的超時時間到達後,調用alarm的進程將收到SIGALRM信號。
alarm系統調用的原型為:
#include <unistd.h>在這一過程中,系統將依次產生下列事件。
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信號