一 信號的基本概念
信號:是向進程發送的軟件通知,通知進程有事件發生。
生成:表示一個信號的產生。
捕獲:表示接收到一個信號。
信號的壽命:信號的生成和傳遞之間的時間間隔。
掛起的信號:已經生成但還未被傳遞的信號。
二 產生信號
每個信號名都是以SIG開頭,信號的名字都定義在signal.h中,POSIX必需的信號如下:
?
信號 描述
SIGABRT 進程放棄(signal abort)
SIGALRM 告警時鐘(signal alarm)
SIGBUS 訪問了內存對象中的為定義部分
SIGCHLD 子進程被終止,停止或繼續(signal child)
SIGCONT 如果進程被停止了,本信號使進程繼續執行(signal continue)
SIGFPE 算術計算中出現了被零除這樣的錯誤
SIGHUP 在控制終端(進程)上掛起(死亡)
SIGILL ? 無效的硬件指令
SIGINT 交互終端提示信號(通常是Ctrl-C)
SIGKILL 終止(signal kill)
SIGPIPE 向一個沒有讀程序的管道寫入(signal pipe)
SIGQUIT 交互終端終止(通常是Ctrl-l)(signal quit)
SIGSEGV ? 無效的內存引用
SIGSTOP ? 執行停止(signal stop)
SIGTERM 終止(signal terminate)
SIGTTIN 后臺進程試圖進行讀操作(signal try to input)
SIGTTOU ? 后臺進程試圖進行寫操作(signal try to output)
SIGURG 在套接字上有高速寬數據
SIGUSR1 ? 用戶定義的信號1
SIGUSR2 ? 用戶定義的信號2
1? 函數kill
#include <signal.h> int kill(pid_t pid, //進程ID
int sig //信號碼
); //成功返回0,不成功返回-1并設置errno
參數pid的取值:>0??????? kill就向那個ID表示的進程發送信號
? =0 kill就向調用程序的進程組成員發送信號
? -1 kill就向所有它有權發送信息的進程發送信號
其它負值 就將信號發送到組ID等于|pid|的進程組中去
kill的實現必須檢測的錯誤及相應的錯誤碼:EINVAL:sig是一個無效的或不被支持的信號
EPERM:調用程序沒有適當的權限
ESRCH:沒有進程或進程組對應于pid
例子:向進程1000發送SIGUSR1
if (kill( 1000 ,SIGUSR1)){ perro( " Failed to send the SIGUSR1 signal " ); }
注:查找相關進程ID的常用方法是使用getpid(獲取當前進程ID),getppid(獲取當前進程的父進程ID),getpgid(獲取當前進程的進程組ID),或者通過保存從fork中返回的值來查找。
2 函數raise
#include <signal.h> int raise( int sig); //成功,返回0,不成功如果sig是無效的,raise函數就將error設置為EINVAL
raise函數用來向自己發送一個信號。
例子:使進程向自己發送一個SIGUSR1信號
if (raise(SIGUSR1)!= 0 ){ perror( " Failed to raise SIGUSR1 " ); }
3 函數alarm
#include <unistd.h>
unsigned alarm(unsigned seconds);
alarm函數用來在seconds秒之后安排發送一個SIGALRM信號,alarm函數從來不報告錯誤。
?
三 對信號掩碼和信號集的操作
信號掩碼:當前被阻塞的信號的集合,類型為sigset_t.
對信號集的操作由以下五個函數組成:
#include <signal.h> int sigaddset(sigset_t * set , int signo); //將signo加入信號集 int sigdelset(sigset_t * set , int signo); //將signo從信號集中刪除 int sigemptyset(sigset_t * set ); //對信號集初始化,使其不包含任何信號 int sigfillset(sigset_t * set ); //對信號集初始化,使其包含所有信號 int sigismember( const sigset_t * set , int signo); //報告signo是否在*set中,如果在,返回1,否則返回0
例子:對信號集twosigs進行初始化,使其包含兩個信號SIGINT和SIGQUIT
if ((sigemptyset(&twosigs)==- 1 || sigaddset(&twosigs,SIGINT)==- 1 || sigaddset(&twosigs,SIGQUIT)==- 1 )){ perror( " Failed to set up signal mask " ); }
進程可以用sigprocmask函數來檢查或修改它的進程信號掩碼,sigprocmask函數可以根據參數how指定的方法修改進程的信號掩碼。新的信號掩碼由參數set指定,而原先的信號掩碼將保存到信號集oset中,聲明如下:
#include <signal.h> int signalprocmask( int how, //用來說明信號掩碼的修改方式
const sigset_t *restrict set , //指向一個信號集的指針,在修改中要用到這個信號集,如果為NULL,就說明不需要進行修改
sigset_t *restrict oset //如果不為NULL,sigprocmask會將修改之前的信號集放在*oset中返回
);
參數how取以下三個值中的一個:
SIG_BLOCK:向當前被阻塞的信號中添加一個信號集
SIG_UNBLOCK:從當前被阻塞的信號中刪除一個信號集
SIG_SETMASK:將指定的信號集設置為被阻塞的信號
例子:將SIGINT添加到進程已經阻塞的信號集中去
sigset_t newsigset; if ((sigemptyset(&newsigset)==- 1 || sigaddset(&newsigset,SIGINT)==- 1 )){ perror( " Failed to initialize the signal set " ); } else if (sigprocmask(SIG_BLOCK,&newsigset,NULL)==- 1 ){ perror( " Failed to block SIGINT " ); }
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
