信號

1、概念

    ctrl-c給進程發送一個SIGINT的信號,這個信號的默認處理動作是終止進程,ctrl-c產生的信號只能發給前臺進程

    進程收到信號,不是立即處理,而是先記錄起來恰當時候再處理

2、信號列表

     使用kill -l顯示系統的所有信號,1-31爲普通信號(31個),34-64爲實時信號(31個)

3、產生信號

  (1)通過鍵盤發送信號給前臺,例如ctrl-c產生SIGINT信號,ctrl-\產生SIGQUIT信號,ctrl-z產生SIGTSTP信號

wKiom1d_4yCj2Y1NAAAwDjTQMUQ031.png

 (2)硬件異常


 (3)通過指令

 alarm函數

#include<stdio.h>
#include<unistd.h>
int  main()
{
 int count=0;
 alarm(1);
 for(;2;count++){
  printf("count=%d\n",count);
 }
 return 0;

}

wKioL1d_4vuzFDARAAAa-m-PmII714.png

此函數作用爲:1秒鐘不停的數數,1秒鐘到了就被SIGALRM信號終止

4、信號處理(信號遞達)

 (1)忽略信號

 (2)執行默認處理動作

 (3)自定義處理信號的函數(捕捉信號)

5、阻塞信號

    實際執行信號的處理動作,稱爲信號遞達;信號從產生到遞達之間的狀態,稱爲信號未決。進程可以選擇阻塞某個信號,被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞,才執行遞達的動作。

    阻塞是暫時不處理此信號,而忽略則是處理此信號;信號產生與阻塞無關,遞達與解除阻塞無關

信號在內核中的表示示意圖 

wKiom1eAdRrB-DqHAACpwfXtLe8959.png


    POSIX.1允許系統遞送該信號一次或多次,常規信號在遞達之前產生多次只計一次,而實時信號在遞達之前產生多次可以依次放在一個隊列裏。圖中每個信號只有一個bit的未決標誌,非0 即1,不記錄該信號產生了多少次,阻塞信號也這樣表示

     未決和阻塞標誌用相同的數據類型sigset_t來存儲,sigset_t稱爲信號集

     阻塞信號集也稱爲當前進程的信號屏蔽字

6、信號集操作函數

   #include<signal.h>

   int sigemptyset(sigset_t  *set)//使所有信號對應的bit清零(初始化狀態)

   int sigfillset(sigset_t  *set)//使所有信號對應的bit置位(初始化)

   int sigaddset(sigset_t  *set, int signo)//添加某種信號

   int sigdelset(sigset_t  *set, int signo)//刪除某種信號

   int sigismember(const sigset_t  *set, int signo)//布爾函數,判斷信號集有效信號中是否包含某種信號,包含返回1,不包含返回0,出錯返回-1

7、sigprocmask

     調用函數sigprocmask可以讀取或更改進程的信號屏蔽字

函數原型:

  #include<signal.h>

  int sigprocmask(int how, const sigset_t *set, sigset_t *oset)

  返回值:若成功則爲0,若出錯爲-1

  若oset是非空指針,則讀取進程的當前信號屏蔽字通過oset參數傳出;若set是非空指針,則更改進程的信號屏蔽字由how指示如何更改;若oset和set都是非空指針,則先將原來的信號屏蔽字備份到oset裏,然後根據set和how參數更改信號屏蔽字

   如果調用sigprocmask解除了對當前若干個未決信號的阻塞,則在sigprocmask返回前,至少將其中一個信號遞達。

 8、sigpending

   #include<signal.h>

   int sigpending(sigset_t *set)

  sigpending讀取當前進程的未決信號集,通過set參數傳出,調用成功返回0,出錯返回-1

 

幾個函數的代碼實現:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void printsigset(sigset_t *set)
{
 int i=0;
 for(;i<32;i++){
  if(sigismember(set, i)){  // 判斷指定信號是否在目標集合中
   putchar('1');
  }else{
   putchar('0');
  }
 }
 puts("\0");
}
int main()
{
 sigset_t s,p;
 sigemptyset(&s);  // 定義信號集對象,並清空初始化
 sigaddset(&s,SIGINT);  // ctrl-c操作
 sigprocmask(SIG_BLOCK,&s,NULL); //設置阻塞信號集,設置SIGINT信號
  while(1){
   sigpending(&p);  //獲取未決信號集
   printsigset(&p);
   sleep(1);
  }
 return 0;
}

wKiom1eAoMyRqSPGAAAdWw970Ug262.png


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章