linux中的信號機制


  

  
  • 概述
  Linux信號機制是在應用軟件層次上對 中斷機制的一種模擬,信號提供了一種處理異步事件的方法,例如,終端用戶輸入中斷鍵(ctrl+c),則會通過信號機制停止一個程序 [1]
  這其實就是向那個程序(進程)發送一個SIGINT信號。每個進程都有一個自己私有的信號 處理函數映射表,當該進程成收到一個信號時,對應的信號處理函數被觸發執行。而一個進程可以向另外一個進程發送信號,也可以向自己發送信號;操作系統內核也可以向一個進程發送信號,以通知某些硬件事件。 信號處理函數映射表中共有64個表項。前32個信號,編號為1 ~ 31,有預定義的含義和處理函數;后32個作為擴充 [2]。在終端輸入命令“kill -l”就可以看到系統所支持所有的信號。
 
  • 信號機制的兩個常用函數

  

    signal

#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);

返回值:若成功則返回信號以前的處理配置,如果出差則返回SIG_ERR;
或者用如下的定義:

typedef void (*sighandler_t)(int);
sighandler_t signal(int signo, sighandler_t handler);

這個函數的功能是捕捉到相應的信號(signo),並用相應的處理函數(func/handler)來對信號進行相應的相應,是會替代原來的處理函數。但是要和足以,SIGKILL和SIGSTOP這兩個信號是既不能被捕捉也不能被忽略的!(當時我們做一個后台程序,我還想用捕捉SIGKILL的方式來免殺呢)。

  KILL

#include<signal.h>
int kill(pid_t pid, int sig);


這個函數的功能是將信號發送給進程或者進程組。

pid > 0  :要發送信號的進程號

pid = 0  :信號被發送到所以和當前進程在同一個進程組的進程

pid = -1 : 信號發送給發送進程有權限向他們發送信號的系統上的所以進程

pid < -1 :信號發送給其進程組ID等於pid的絕對值

  • 幾個比較常用的信號

SIGIGN:忽略改信號

SIGDEF:采用系統默認方式處理信號

SIGCHLD:在一個進程終止或者停止時,將該信號發送給其父進程,父進程的wait函數通常用來捕捉這個信號

SIGINT:當用戶按中斷鍵(delete/ctrl+c)時將產生這個信號

SIGKILL:此信號可以用於殺死一個進程

SIGSTOP:這是個作業控制信號,用於停止一個進程   這個信號和SIGKILL是僅有的兩個不能被捕獲或忽略的信號

SYSUSR1/2:用戶定義的信號,用於應用程序

  • 程序演示

 

 

/*************************************************************************
    > File Name: signal.c
    > Author: he xingjie
    > Mail: gxmshxj@163.com 
    > Created Time: Fri 25 Oct 2013 07:53:56 AM PDT
 ************************************************************************/

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

void my_func(int sig_no){
    if(sig_no == SIGUSR1)
        printf("Receive SIGUSR1.\n");
    if(sig_no == SIGUSR2)
        printf("Receive SIGUSR2.\n");
    if(sig_no == SIGINT)
        printf("Receive SIGINT.\n"); 
}

int main(void)
{
    if(signal(SIGUSR1, my_func) == SIG_ERR)
        printf("can't catch SIGUSR1.\n'");
    if(signal(SIGUSR2, my_func) == SIG_ERR)
        printf("can't catch SIGUSR2.\n'");
    if(signal(SIGINT, my_func) == SIG_ERR)
        printf("can't catch SIGINT.\n'");

    kill(getpid(),SIGINT);

    while(1);
    return 0;
}

當運行這個程序的時候,我們將會看到:Receive SIGINT.  然后程序不斷在循環,如果我們按ctrl+c,將會輸出:Receive SIGINT.

如果我們把程序放在后天運行,並且用 kill -USR1 pid。pid為那個進程的id,我們還將會看到Receive SIGUSR1.

  • 參考資料

  [1] UNIX環境高級編程

  [2]  我們老師上課的課件

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM