歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

《APUE》:信號處理

程序簡介:在Unix環境下,我們可以讓程序屏蔽掉某些信號(SIGKILL信號和SIGSTOP除外),這個例子演示了這方面的功能。

//《APUE》程序10-11:信號處理和sigprocmask實例
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

//輸出錯誤信息並退出
void error_quit(const char *str)
{
fprintf(stderr, "%s\n", str);
exit(1);
}

//SIGQUIT信號的處理函數
void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if( SIG_ERR == signal(SIGQUIT, SIG_DFL) )
error_quit("can't reset SIGQUIT");
}

int main(void)
{
sigset_t newmask, oldmask, pendmask;
//設置對SIGQUIT信號的處理函數
if( SIG_ERR == signal(SIGQUIT, sig_quit) )
error_quit("can't catch SIGQUIT");

//將newmask信號集初始化為空
sigemptyset(&newmask);
//在newmask信號集中增加SIGQUIT信號
sigaddset(&newmask, SIGQUIT);

int temp;
//將oldmask設置為當前的屏蔽信號集(方便以後恢復)
//在當前的屏蔽信號添加增加newmask信號集
temp = sigprocmask(SIG_BLOCK, &newmask, &oldmask);
if( temp < 0 )
error_quit("SIG_BLOCK error");

sleep(5);

//返回當前的屏蔽信號集
temp = sigpending(&pendmask);
if( temp < 0 )
error_quit("sigpending error");
//檢查SIGQUIT信號是否在pendmask信號集中
if( sigismember(&pendmask, SIGQUIT) )
printf("\nSIGQUIT pending\n");

//恢復屏蔽信號集
temp = sigprocmask(SIG_SETMASK, &oldmask, NULL);
if( temp < 0 )
error_quit("SIG_SETMASK error");
printf("SIGQUIT unblocked\n");

sleep(5);
return 0;
}
運行示例:

www.linuxidc.com @ubuntu:~/code$ gcc temp.c -o temp
www.linuxidc.com @ubuntu:~/code$ ./temp
^\ #產生一次SIGQUIT信號
SIGQUIT pending #從sleep返回後
caught SIGQUIT #在信號處理程序中
SIGQUIT unblocked #從sigpromask返回後
^\退出 #再次產生信號

www.linuxidc.com @ubuntu:~/code$ ./temp #再次運行程序
^\^\^\^\^\^\^\^\^\^\^\^\ #產生多次SIGQUIT信號
SIGQUIT pending
caught SIGQUIT #只接收到一次信號
SIGQUIT unblocked
^\退出

結論:

1:進程阻塞了SIGQUIT信號,在此期間所產生的SIGQUIT信號都會被阻塞,直到該信號不再被阻塞。

2:在休眠期間,如果產生了信號,那麼此時的信號是未決的,但是不再受阻塞(所以在退出之前,sig_quit函數可以被調用)

3:在信號被阻塞期間系統不會對信號進行排隊。

注解(這段話是從網上摘抄的):

信號的”未決“是一種狀態,指的是從信號的產生到信號被處理前的這一段時間;信號的”阻塞“是一個開關動作,指的是阻止信號被處理,但不是阻止信號產生。

APUE例題在sleep前用sigprocmask阻塞了退出信號,然後sleep,然後在sleep的過程中產生一個退出信號,但是此時退出信號被阻塞過,(中文的”阻塞”在這裡容易被誤解為一種狀態,實際上是一種類似於開關的動作,所以說“被阻塞過”,而不是“被阻塞”)所以處於“未決”狀態,在 sleep後又用sigprocmask關掉退出信號的阻塞開關,因為之前產生的退出信號一直處於未決狀態,當關上阻塞開關後,馬上退出“未決”狀態,得到處理,這一切發生在sigprocmask返回之前。
 

Copyright © Linux教程網 All Rights Reserved