linux进程中对信号的屏蔽,linux进程中的信号屏蔽
在linux的進程中可以接收到各種的信號,并且如果你不對信號進行處理,linux中的進程就會采用默認的處理方式處理,比如ctrl-c的信號,進程對它的處理就是終止進程的執行。
在linux中,我們也可以在進程中屏蔽掉某些信號,使進程不去處理這些信號,但其中的SIGKILL和SIGSTOP是不能被阻塞的。
在這里先介紹幾個信號的函數:
int sigempty(sigset_t *set);???????????????? // 清空信號集set
int sigfillset(sigset_t *set);?????????????????? // 填滿信號集,即讓set包含所有的信號
int sigaddset(sigset_t *set, int signo);? // 在set中增加signo信號
int sigdelset(sigset_t *set, int signo);?? // 在set中去掉signo信號
int sigismember(sigset_t *set, int signo); // 信號signo是否在信號集set中
int sigprocmask(int how, const sigset_t set, sigset_t oset); // 若oset非空,則進程的當前信號屏蔽字通過oset返回,若set是一個非空指針,著參數how指示如何修改當前信號的屏蔽字,how可以取三個值:
SIG_BLOCK:增加一個信號。
SIG_UNBLOCK:解除一個信號。
SIG_SETMASK:該進程的信號將被set信號集取代。
int sigpengding(sigset_t *set);? // 該函數返回信號集,該信號通過set參數返回。
以上函數都在#include 頭文件中。
下面用《unix環境高級編程》里的一個例子說明一下,代碼有所修改,先看代碼(main.c,里面有個人對代碼的注釋):
view plaincopy to clipboardprint?
#include
#include
#include
static void sig_quit(int);
int
main(void)
{
sigset_t newmask, oldmask, pendingmask;
//設置對信號SIGQUIT的處理函數
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
fprintf(stderr, "can't catch SIGQUIT/n");
exit(1);
}
//設置一個空的信號集
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT); // 在這個信號集中增加SIGQUIT信號
//在當前進程中增加newmask信號集作為屏蔽信號集,oldmask返回當前進程的信號集
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
fprintf(stderr, "SIG_BLOCK error/n");
exit(1);
}
sleep(5);
//返回當前進程信號集
if (sigpending(&pendingmask) < 0)
{
fprintf(stderr, "sigpending error/n");
exit(1);
}
//檢查SIGQUIT信號是否在當前信號集中
if (sigismember(&pendingmask, SIGQUIT))
printf("/nSIGQUIT pending/n");
//恢復進程的信號集
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
fprintf(stderr, "SIG_SETMASK error/n");
exit(1);
}
printf("SIGQUIT unblocked/n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT/n");
//恢復進程對SIGQUIT的默認處理
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
fprintf(stderr, "can't reset SIGQUIT/n");
exit(0);
}
}
#include
#include
#include
static void sig_quit(int);
int
main(void)
{
sigset_t newmask, oldmask, pendingmask;
//設置對信號SIGQUIT的處理函數
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
fprintf(stderr, "can't catch SIGQUIT/n");
exit(1);
}
//設置一個空的信號集
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT); // 在這個信號集中增加SIGQUIT信號
//在當前進程中增加newmask信號集作為屏蔽信號集,oldmask返回當前進程的信號集
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
fprintf(stderr, "SIG_BLOCK error/n");
exit(1);
}
sleep(5);
//返回當前進程信號集
if (sigpending(&pendingmask) < 0)
{
fprintf(stderr, "sigpending error/n");
exit(1);
}
//檢查SIGQUIT信號是否在當前信號集中
if (sigismember(&pendingmask, SIGQUIT))
printf("/nSIGQUIT pending/n");
//恢復進程的信號集
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
fprintf(stderr, "SIG_SETMASK error/n");
exit(1);
}
printf("SIGQUIT unblocked/n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT/n");
//恢復進程對SIGQUIT的默認處理
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
fprintf(stderr, "can't reset SIGQUIT/n");
exit(0);
}
}
編譯: gcc main.c
生成:a.out
運行:./a.out
輸出如下(ubuntu9.10):
^/
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^/退出
下面解釋一下輸出:
^/??????????????????????????????? 在第一次sleep(5)的5秒中內產生信號一次(按ctrl+/)
SIGQUIT pending????????? 從sleep返回后
caught SIGQUIT?????????? 在信號處理函數中
SIGQUIT unblocked?????? 從sigprocmask返回后
^/退出????????????????????????? 再次產生信號
我們對著程序來看下輸出。
在我們設置SIGQUIT屏蔽字和恢復進程的信號集這段時間,我們產生的SIGQUIT信號,我們的進程并沒去處理,所以輸出了SIGQUIT pending 。
在我們恢復進程的信號集后,我們進程就撲捉到了我們剛才產生的信號,因而就輸出了caught SIGQUIT,在sig_quit函數中,我們恢復了SIGQUIT的默認處理方式(即終止進程運行),進程當我們再次產生SIGQUIT信號,進程就退出了。
當我們產生進程時,一些unix系統會對進程中要處理的信號進行排隊,我們的進程會對信號隊列中的信號進行處理。我們再運行一下剛才的程序,在第一次sleep(5)的5秒中內產生信號10次信號,看下會怎么樣,下面是我的輸出:
^/^/^/^/^/^/^/^/^/^/
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^/退出
下面解釋一下輸出:
^/^/^/^/^/^/^/^/^/^/?? 在第一次sleep(5)的5秒中內產生信號10次信號
SIGQUIT pending?????????????? 從sleep返回后
caught SIGQUIT??????????????? 從sigprocmask返回后
SIGQUIT unblocked?????????? 從sigprocmask返回后
^/退出????????????????????????????? 再次產生信號
這里可以看到linux系統對沒有對信號進行排隊,產生10次信號,只處理一次。
在上面的例子中,我們用signal函數來指定信號的處理函數,用sigprocmask來指定信號屏蔽字,其實這些都可以在一個函數中解決,它就是sigaction ,推薦使用sigaction函數。
pthread_sigmask與sigprocmask。前者是線程安全的。
pthread_sigmask改變的是線程的信號集與整個進程無關。
總結
以上是生活随笔為你收集整理的linux进程中对信号的屏蔽,linux进程中的信号屏蔽的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: _int64_在Linux对应对文件,L
- 下一篇: c语言编程切片stl1005无标题,C语