一 信號的基本概念
信號:是向進程發送的軟件通知,通知進程有事件發生。
生成:表示一個信號的產生。
捕獲:表示接收到一個信號。
信號的壽命:信號的生成和傳遞之間的時間間隔。
掛起的信號:已經生成但還未被傳遞的信號。
二 產生信號
每個信號名都是以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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

