1. 程式人生 > >訊號捕捉 、pause函式和SIGCHLD訊號

訊號捕捉 、pause函式和SIGCHLD訊號

一、訊號捕捉

訊號捕捉針對於自定義的函式處理訊號方式。訊號遞達呼叫這個函式稱為捕捉訊號。發生訊號並不是立即處理的,而是找合適的機會,這個機會就是從核心態切換到使用者態的時候處理訊號。

使用者態切換到核心態的方式:(1)系統呼叫(2)程式異常(3)軟體中斷

訊號捕捉流程順序見下圖:

 二、pause函式

呼叫pause函式回事程序掛起,直到有訊號遞達。如果訊號的處理動作是終止程序,則程序終止,pause函式沒有機會返回。

如果訊號的處理動作是忽略的,則程序繼續處於掛起狀態,pause不返回。如果訊號的處理動作為捕捉,則呼叫處理函式之後pause函式返回-1,error設定為EINTR,所以pause只有出錯返回值,沒有成功返回值和我們之前講過的程式替換函式一樣。

三、SIGCHLD訊號

我們之前涉及到的殭屍程序,是由於子程序先於父程序退出,父程序沒有關心子程序的退出狀態導致殭屍程序。其實子程序退出會給父程序傳送一個訊號就是SIGCHLD。之前避免殭屍程序一種方法就是阻塞式的等待,父程序就不能處理自己的工作。第二種就是waitpid輪詢等待的方式,但是這種父程序一邊要處理自己的工作,另外一邊還要輪詢查詢子程序是否結束,這樣程式實現起來比較複雜。

我們可以使用該訊號來處理殭屍程序,通過對該訊號的自定義處理函式,然後父程序只管處理自己的事情,如果該訊號到來父程序去處理,處理完畢之後接著做父程序的事情。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<sys/wait.h>
void sigcb(int signo)
{
  while(waitpid(-1,0,WNOHANG)>0)
  {
    printf("signo:%d\n",signo);
  }
}

int main()
{
  signal(SIGCHLD,sigcb);
  int pid = fork();
  if(pid<0)
  {
    perror("fork error");
    exit(1);
  }
  else if(pid == 0)
  {
    sleep(5);
    exit(1);
  }
  else 
  {
    while(1)
    {
      printf("waiting!!!\n");
      sleep(1);
    }
  }
  return 0;
}