Linux下的signal訊號機制

來源:互聯網
上載者:User

在Linux中,要發送一個訊號相當容易。程式員需要知道兩個資訊:要發送哪個訊號,將這個訊號發送給哪個進程。可以用 man 7 signal 找到一個可以利用的訊號的列表。使用者可以只將訊號發送給使用者自己的進程,也可以以root身份運行從而將訊號發送給任意一進程。

 

Source:

#include<stdio.h><br />#include<signal.h><br />#include<unistd.h><br />#include<stdlib.h><br />void when_alarm();<br />void when_sigint();<br />void when_sigchld(int);<br />void when_sigusr1();<br />void when_sigio();<br />int main()<br />{<br /> int childpid;//子程式進程ID號<br /> printf("程式已經開始運行,5秒鐘後將接收到時鐘訊號。/n");<br /> if ((childpid=fork())>0)//父進程<br /> {<br /> signal(SIGALRM,when_alarm); //當接收到SIGALRM訊號時,調用when_alarm函數<br /> signal(SIGINT,when_sigint); //當接收到SIGINT訊號時,調用when_sigint函數<br /> signal(SIGCHLD,when_sigchld);//當接收到SIGCHLD訊號時,調用when_sigchld函數<br /> signal(SIGUSR1,when_sigusr1);//當接收到SIGUSR1訊號時,調用when_sigusr1函數<br /> signal(SIGIO,when_sigio);//當接收到SIGIO訊號時,調用when_sigio函數<br /> alarm(5); //5秒鐘之後產生SIGALRM訊號<br /> raise(SIGIO); //向自己發送一個SIGIO訊號<br /> pause(); //將父進程暫停下來,等待SIGALRM訊號到來<br /> pause(); //將父進程暫停下來,等待SIGUSR1訊號到來<br /> pause(); //將父進程暫停下來,等待SIGCHLD訊號到來<br /> printf("------此時程式會停下來等待,請按下ctrl+c送出SIGINT訊號-------/n");<br /> pause(); //將父進程暫停下來,等待SIGINT訊號到來<br /> }<br /> else if(childpid==0) //子進程<br /> {<br /> int timer;<br /> for(timer=7;timer>=0;timer--) //時鐘計時5秒產生SIGALRM訊號,再過2秒子進程退出,產生SIGCHLD訊號<br /> {<br /> if(timer>2)<br /> printf("距離SIGALRM訊號到來還有%d秒。/n",timer-2);<br /> if(timer==4)<br /> kill(getppid(),SIGUSR1); //向父進程發送一個SIGUSR1訊號<br /> if((timer<=2)&&(timer>0))<br /> printf("子進程還剩%d秒退出,屆時會產生SIGCHLD訊號。/n",timer);<br /> if(timer==0) //子進程退出,產生SIGCHLD訊號<br /> raise(SIGKILL); //子進程給自己發一個結束訊號<br /> sleep(1); //每個迴圈延時1秒鐘<br /> }<br /> }<br /> else<br /> printf("fork()函數調用出現錯誤!/n");<br /> return 0;<br />}<br />void when_alarm()<br />{<br /> printf("5秒鐘時間已到,系統接收到了SIGALRM訊號!/n");<br />}<br />void when_sigint()<br />{<br /> printf("已經接收到了SIGINT訊號,程式將退出!/n");<br /> exit(0);<br />}<br />void when_sigchld(int SIGCHLD_num)<br />{<br /> printf("收到SIGCHLD訊號,表明我的子進程已經中止,SIGCHLD訊號的數值是:%d。/n",SIGCHLD_num);<br />}<br />void when_sigusr1()<br />{<br /> printf("系統接收到了使用者自訂訊號SIGUSR1。/n");<br />}<br />void when_sigio()<br />{<br /> printf("系統接收到了SIGIO訊號。/n");<br />}<br /> 

 

Result:

 

[work@db-testing-com06-vm3.db01.baidu.com c++]$ ./signal_test 

程式已經開始運行,5秒鐘後將接收到時鐘訊號。

距離SIGALRM訊號到來還有5秒。

系統接收到了SIGIO訊號。

距離SIGALRM訊號到來還有4秒。

距離SIGALRM訊號到來還有3秒。

距離SIGALRM訊號到來還有2秒。

系統接收到了使用者自訂訊號SIGUSR1。

距離SIGALRM訊號到來還有1秒。

5秒鐘時間已到,系統接收到了SIGALRM訊號!

子進程還剩2秒退出,屆時會產生SIGCHLD訊號。

子進程還剩1秒退出,屆時會產生SIGCHLD訊號。

收到SIGCHLD訊號,表明我的子進程已經中止,SIGCHLD訊號的數值是:17。

------此時程式會停下來等待,請按下ctrl+c送出SIGINT訊號-------

已經接收到了SIGINT訊號,程式將退出!

 

 

訊號參考對照表:

Signal

Description

SIGABRT

由調用abort函數產生,進程非正常退出

SIGALRM

用alarm函數設定的timer逾時或setitimer函數設定的interval timer逾時

SIGBUS

某種特定的硬體異常,通常由記憶體訪問引起

SIGCANCEL

由Solaris Thread Library內部使用,通常不會使用

SIGCHLD

進程Terminate或Stop的時候,SIGCHLD會發送給它的父進程。預設情況下該Signal會被忽略

SIGCONT

當被stop的進程恢複啟動並執行時候,自動發送

SIGEMT

和實現相關的硬體異常

SIGFPE

數學相關的異常,如被0除,浮點溢出,等等

SIGFREEZE

Solaris專用,Hiberate或者Suspended時候發送

SIGHUP

發送給具有Terminal的Controlling Process,當terminal被disconnect時候發送

SIGILL

非法指令異常

SIGINFO

BSD signal。由Status Key產生,通常是CTRL+T。發送給所有Foreground Group的進程

SIGINT

由Interrupt Key產生,通常是CTRL+C或者DELETE。發送給所有ForeGround Group的進程

SIGIO

非同步IO事件

SIGIOT

實現相關的硬體異常,一般對應SIGABRT

SIGKILL

無法處理和忽略。中止某個進程

SIGLWP

由Solaris Thread Libray內部使用

SIGPIPE

在reader中止之後寫Pipe的時候發送

SIGPOLL

當某個事件發送給Pollable Device的時候發送

SIGPROF

Setitimer指定的Profiling Interval Timer所產生

SIGPWR

和系統相關。和UPS相關。

SIGQUIT

輸入Quit Key的時候(CTRL+/)發送給所有Foreground Group的進程

SIGSEGV

非法記憶體訪問

SIGSTKFLT

Linux專用,數學副處理器的棧異常

SIGSTOP

中止進程。無法處理和忽略。

SIGSYS

非法系統調用

SIGTERM

請求中止進程,kill命令預設發送

SIGTHAW

Solaris專用,從Suspend恢複時候發送

SIGTRAP

實現相關的硬體異常。一般是調試異常

SIGTSTP

Suspend Key,一般是Ctrl+Z。發送給所有Foreground Group的進程

SIGTTIN

當Background Group的進程嘗試讀取Terminal的時候發送

SIGTTOU

當Background Group的進程嘗試寫Terminal的時候發送

SIGURG

當out-of-band data接收的時候可能發送

SIGUSR1

使用者自訂signal 1

SIGUSR2

使用者自訂signal 2

SIGVTALRM

setitimer函數設定的Virtual Interval Timer逾時的時候

SIGWAITING

Solaris Thread Library內部實現專用

SIGWINCH

當Terminal的視窗大小改變的時候,發送給Foreground Group的所有進程

SIGXCPU

當CPU時間限制逾時的時候

SIGXFSZ

進程超過檔案大小限制

SIGXRES

Solaris專用,進程超過資源限制的時候發送

==========================================================================

signal學習推薦:


訊號(signal)介紹(Linux中國)

http://www.linux-cn.com/html/linux/system/20070505/27605.shtml

 

Linux 訊號signal處理函數(CSDN)

http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945535.aspx

 

Linux 訊號signal處理機制(CSDN)

http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945380.aspx

 

==========================================================================
         程式員可以調用 int raise(int signo) 將一個訊號發送給它自己。這個函數只帶有一個參數,既要發送訊號的編號。如:raise(SIGINT); raise(SIGKILL);
         讓人感興趣的是函數 unsigned int alarm(unsigned int seconds) 它可以讓使用者進程在將來某個指定的時間接收到一個訊號。alarm()的唯一參數是將來訊號SIGALRM應該在多少秒以後發送給使用者進程。當使用者調用alarm()時,前面任何一個請求的警示訊號(不包括懸掛起來被阻塞的SIGALRM訊號)都將被取消,調用的傳回值是前面請求的剩餘時間。alarm()範例如下:
    
if(signal(SIGALRM,alarmhandler)==SIG_ERR)
{
     printf("Couldn't register signal handler./n"); 
}
alarm(5);      // 5秒鐘以後,程式將會收到一個SIGALRM訊號
for(i=0;i<10;i++)
{
     sleep(3);
}
void alarmhandler(int signum)
{
     printf("alarmhandler./n"); 
}

         也可以使用 int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue) 來實現更精確更方便的定時控制。
         參數which一般取ITIMER_REAL,它使得使用者的計時器根據系統時鐘來計算時間。當計數時間到期時,它將發送一個SIGALRM訊號。其功能和alarm()一樣,所以使用者不能將兩者同時使用。
         結構itimerval的定義如下:
struct itimerval 

     struct timeval it_interval; // 每一次觸發警示後應該被複位的值,為0警示被禁止
     struct timeval it_value;     // 下一次觸發警示的時間,為0警示將只觸發一次
};
         結構timeval的定義如下:
strut timeval

     long tv_sec;       // 秒數 
     long tv_usec;     // 微秒數
};
         setitimer()範例如下:

struct itimerval itimer;
itimer.it_interval.tv_usec = 0;     // it_interval欄位指定了每一次觸發後應該被複位的值
itimer.it_interval.tv_sec     = 2;

itimer.it_value.tv_usec = 0;        // it_value欄位指定了直到下一次觸發的時間   
itimer.it_value.tv_sec     = 5;
setitimer(ITIMER_REAL,&itimer,NULL);

for(i=0;i<10;i++)
{
     sleep(3);
}

void alarmhandler(int signum)
{
     printf("alarmhandler./n"); 
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.