1. 函数signal
void (*signal(int signo, void(*func)(int)))(int);
func是常量SIG_IGN时,向内核表示忽略此信号,SIGKILL和SIGSTOP不能忽略;是常量SIG_DFL,表示借到此信号后的动作是系统默认动作;是函数地址时,代表信号处理程序或信号捕捉函数。
<span style="font-size:18px;">#include "apue.h"
static void sig_usr(int); // one handler for both signals
int main(void)
{
if(signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("can't catch SIGUSR1");
if(signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("can't catch SIGUSR2");
for(;;)
pause();
}
static void sig_usr(int signo)
{
if(signo == SIGUSR1)
printf("received SIGUSR1\n");
else if(signo == SIGUSR2)
printf("received SIGUSR2\n");
else
err_dump("received signal %d\n", signo);
}
</span>
2. kill函数和raise
int kill(pid_t pid, int signo); //pid>0(信号发送给进程ID为pid的),pid = 0(与发送进程属于统一进程组),pid < 0(进程组ID等于pid的绝对值),pid = -1(信号发送进程有权限发送的所有进程)
int raise(int signo); // raise(signo) 等价于 kill(getpid(), signo)
3. 信号集
int sigemptyset(sigset_t *set); //初始化信号集,置为空集
int sigfillset(sigset_t *set); //初始化由set指向的信号集,使其包括所有的信号
int sigaddset(sigset_t *set, int signo); //将严格信号添加到已有信号集中
int sigdelset(sigset_t *set, int signo); //从信号集中删除一个信号
int sigismember(sigset_t *set, int signo); //判断是否是信号集的一个信号
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
how为SIG_BLOCK时,为当前屏蔽字与set的并集,为SIG_UNBLOCK时,为当前屏蔽字与set的补集的交集,为SIG_SETMASK时,用set设置屏蔽字;oset为原屏蔽字的。
int sigpending(sigset_t *set);
<span style="font-size:18px;">#include <signal.h>
#include <errno.h>
#include "apue.h"
#define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)
/*int sigaddset(sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
*set |= (1 << (signo - 1));
return 0;
}
int sigdelset(sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
*set &= ~(1 << (signo - 1));
return (0);
}
int sigismember(sigset_t *set, int signo)
{
if(SIGBAD(signo)){
errno = EINVAL;
return (-1);
}
return ((*set & (1 << (signo - 1))) != 0);
}*/
static void sig_quit(int);
int main(void)
{
sigset_t newmask, oldmask, pendmask;
if(signal(SIGQUIT, sig_quit) == SIG_ERR)
err_sys("can't catch SIGQUIT");
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
sleep(5);
if(sigpending(&pendmask) < 0)
err_sys("sigpending error");
if(sigismember(&pendmask, SIGQUIT))
printf("\nSIGQUIT pending\n");
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
printf("SIGQUIT unblocked\n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
err_sys("can't reset SIGQUIT");
}
/***********************
^\^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^\Quit (core dumped)
***********************/
</span>
4. sigsetjmp 和 siglongjump
int sigsetjmp(sigjmp_buf env, int savemask);
int siglongjmp(sigjmp_buf env, int val);
5. sigsuspend
int sigsuspend(const sigset_t *sigmask); //进程屏蔽字设置为sigmask指向的值,在捕捉了一个信号或者发生了一个会终止进程的信号之前,该进程被挂起。
<span style="font-size:18px;">#include <errno.h>
#include "apue.h"
static void sig_int(int);
void pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno;
if(sigprocmask(0, NULL, &sigset) < 0) {
err_ret("sigprocmask erro");
} else{
printf("%s", str);
if(sigismember(&sigset, SIGINT))
printf(" SIGINIT");
if(sigismember(&sigset, SIGQUIT))
printf(" SIGQUIT");
if(sigismember(&sigset, SIGUSR1))
printf(" SIGUSR1");
if(sigismember(&sigset, SIGALRM))
printf(" SIGALRM");
printf("\n");
}
errno = errno_save;
}
int main(void)
{
sigset_t newmask, oldmask, waitmask;
pr_mask("program start: ");
if(signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGUSR1);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
pr_mask("in critical region: ");
if(sigsuspend(&waitmask) != -1)
err_sys("sigsuspend error");
pr_mask("after return from sigsuspend: ");
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
pr_mask("program exit: ");
exit(0);
}
static void sig_int(int signo)
{
pr_mask("\n in sigint: ");
}
/***************************************
program start:
in critical region: SIGINIT
^C
in sigint: SIGINIT SIGUSR1
after return from sigsuspend: SIGINIT
program exit:
***************************************/
</span>
上面的是保护代码临界区,使其不被特定信号中断的正确方法
<span style="font-size:18px;">#include "apue.h"
volatile sig_atomic_t quitflag;
static void sig_int(int signo)
{
if(signo == SIGINT)
printf("\ninterrupt\n");
else if(signo == SIGQUIT)
quitflag = 1;
}
int main(void)
{
sigset_t newmask, oldmask, zeromask;
if(signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal(SIGINT) error");
if(signal(SIGQUIT, sig_int) == SIG_ERR)
err_sys("signal(SIGQUIT) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
while(quitflag == 0)
sigsuspend(&zeromask);
quitflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
exit(0);
}
</span>
输出的结果跟预期不一样。
6. abort函数
void abort(void); //使程序异常终止