生活随笔
收集整理的這篇文章主要介紹了
信号:基本概念
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1、概念和概述
信號是事件發(fā)生時對進(jìn)程的通知機(jī)制,也叫軟件中斷,類似于硬件中斷,信號會打斷程序的正常執(zhí)行流程,而且,信號是異步發(fā)生的,也就是說,無法得知信號的確切發(fā)生時間。
一個進(jìn)程可以向另一個進(jìn)程發(fā)送信號,這可以用作進(jìn)程間的簡單通信。進(jìn)程也可以給自身發(fā)送信號。下面是引發(fā)信號的事件:
硬件發(fā)生異常;用戶鍵入了特殊的終端控制字符,如Ctrl+c;發(fā)生了軟件事件;
每個信號都有一個唯一的正數(shù)描述,還有一個符號名。如中斷信號SIGINT,編號是2。
信號可以分為兩大類:內(nèi)核向進(jìn)程發(fā)送的通知事件即標(biāo)準(zhǔn)信號,和實時信號。
信號因某些事件而產(chǎn)生,信號產(chǎn)生后,會稍后被傳遞給某一進(jìn)程,進(jìn)程采取某些措施來響應(yīng)信號。在產(chǎn)生和到達(dá)期間,信號將處于等待(pending)狀態(tài)。
信號到達(dá)后,會根據(jù)具體的信號執(zhí)行不同的默認(rèn)行為:
忽略信號;終止進(jìn)程;產(chǎn)生核心存儲文件;停止進(jìn)程;于之前暫停后再度恢復(fù)進(jìn)程的執(zhí)行; 程序也可以改變對信號的處理方式:
采取默認(rèn)行為;忽略信號;執(zhí)行信號處理程序; 2、改變信號處置:signal函數(shù)
signal函數(shù)可以改變程序?qū)π盘柕奶幚怼6x如下:
#include <signal.h>
void ( *signal(int sig,void (*handler)(int)) )(int);函數(shù)成功返回前一個處理函數(shù),失敗返回SIG_ERR。
這個函數(shù)的定義優(yōu)點復(fù)雜,可以這樣理解:
函數(shù)名是signal,它有兩個參數(shù),第一個參數(shù)是int型的sig,代表信號名;第二個參數(shù)是一個函數(shù)指針,代表具體的信號處理函數(shù)。這個信號處理函數(shù)handler有一個int型的參數(shù),沒有返回(void)。
同時,signal函數(shù)的返回值是一個參數(shù)和返回值和handler函數(shù)一樣的一個函數(shù)指針。
可以采用如下定義來化簡:
typedef void (*sigfunc)(int);這樣,signal函數(shù)的定義變成如下的樣子:
sigfunc signal(int sig,sigfunc handler);signal函數(shù)的第二個參數(shù)除了一個函數(shù)指針外,還可以是下面的值:
- SIG_DFL:默認(rèn)處理;
- SIG_IGN:忽略;
對于具體的使用方法,首先編寫handler函數(shù),里面規(guī)定了具體的信號處理方法,然后使用signal調(diào)用handler,在需要捕獲信號的地方調(diào)用signal函數(shù)即可。
3、信號處理器簡介
信號處理器程序(也叫信號捕獲器)是當(dāng)指定的信號發(fā)生傳遞給進(jìn)程時將會調(diào)用的一個函數(shù)。調(diào)用信號處理器程序,可能會隨時打斷主程序流程:內(nèi)核代表進(jìn)程調(diào)用處理器程序,當(dāng)處理器返回時,返回進(jìn)程被打斷的地方繼續(xù)執(zhí)行。如下圖:
可以看出,和函數(shù)調(diào)用另一個函數(shù)的流程類似。
下面是一個簡單的例子:
#include <signal.h>
#include <stdio.h>
static void handler(int sig)
{printf("ouch!\n");
}
int main(int argc,char *argv[])
{int j;if(signal(SIGINT,handler)==SIG_ERR){printf("signal error\n");return 0;}for(j=0;;j++){printf("%d\n",j);sleep(1);}return 0;
}這里不斷的打印j,程序捕獲SIGINT信號,捕獲后調(diào)用handler函數(shù),handler函數(shù)簡單的打印一句話。結(jié)果如下:
捕獲并處理信號后不影響進(jìn)程的繼續(xù)執(zhí)行。
內(nèi)核調(diào)用信號處理器程序時,將信號作為signal的第一個參數(shù)傳遞??梢栽趆andler中編寫處理多個信號的代碼,這樣就可以根據(jù)傳進(jìn)來的參數(shù)處理具體的信號。
4、顯示信號描述
每個信號都有一串與之相關(guān)的可打印說明,位于sys_siglist數(shù)組中。例如可以使用sys_siglist[SIGINT]獲得對SIGINT的描述。還可以使用strsignal函數(shù)獲得說明:
#define _BSD_SOURCE
#include <signal.h>
extern const char *const sys_siglist[];
#define _FUN_SOURCE
#include <string.h>
char *strsignal(int sig);函數(shù)返回描述符指針。
5、信號集
許多與信號相關(guān)的系統(tǒng)調(diào)用都需要能表示一組不同的信號,可以使用信號集數(shù)據(jù)結(jié)構(gòu)來表示,類型是sigset_t。下面是一些操縱信號集的函數(shù):
int sigemptyset(sigset_t *set):初始化一個沒有信號的信號集,成功返回0,失敗返回-1;int sigfillset(sigset_t *set):初始化一個信號集包含所有信號的信號集,成功返回0,失敗返回-1;int sigaddset(sigset_t *set,int sig):添加信號;int sigdelset(sigset_t *set,int sig):刪除信號;int sigismember(sigset_t *set,int sig):檢查某個信號是否在信號集中; 6、信號掩碼
內(nèi)核為每個進(jìn)程維護(hù)一個信號掩碼,并將阻塞其針對該進(jìn)程的傳遞。如果將阻塞的信號發(fā)送給某個進(jìn)程,那么對該信號的傳遞將延后,直至從進(jìn)程信號掩碼中移除該信號,從而解除阻塞為止。
使用sigprocmask函數(shù)可以修改進(jìn)程的信號掩碼:
#include <signal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);成功返回0,失敗返回-1.
函數(shù)即可以修改信號掩碼,也可以獲取現(xiàn)有掩碼。how參數(shù)指定方式:
SIG_BLOCK:將set的信號添加到信號掩碼中;
SIG_UNBLOCK:將set中的信號從信號掩碼中移除;
SIG_SETMASK:將set設(shè)置為信號掩碼;
7、處于等待狀態(tài)的信號
如果一個進(jìn)程接受了正在阻塞的信號,那么會將該信號添加到進(jìn)程的等待信號集中。之后解除了對該信號的鎖定時,會隨之將信號傳遞給進(jìn)程。sigpending函數(shù)返回那些信號處于等待狀態(tài):
#include <signal.h>
int sigpending(sigset_t *set);
8、信號不排隊
等待信號集只是一個掩碼,表明某個信號是否發(fā)生,而不表明發(fā)生的次數(shù),說明即使信號產(chǎn)生多次,也僅傳遞一次。這個特點在TCP程序中處理SIGCHLD信號時說明過。
9、改變信號處置:sigaction函數(shù)
使用sigaction函數(shù)也可以設(shè)置信號的處理。定義如下:
#include <signal.h>
int sigaction(int sig,const struct sigaction *act,struct sigaction *oldact);sig參數(shù)表示要獲取的信號,可以使除了SIGKILL和SIGSTOP以外的任意信號;
act是一個指向sigaction結(jié)構(gòu)的指針,如果僅對信號的現(xiàn)有處理感興趣,可以設(shè)置為NULL;oldact用來返回之前處理的相關(guān)信息。sigaction結(jié)構(gòu)如下:
struct sigaction {void (*sa_handler)(int);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);
};sa_handler相當(dāng)于signal函數(shù)的handler參數(shù),sa_mask是一個信號掩碼,指定函數(shù)調(diào)用時對特定信號阻塞。sa_flags是一個位掩碼,指定用來控制信號處理過程的各種選項。
總結(jié)
以上是生活随笔為你收集整理的信号:基本概念的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。