===============================================================================
产生被进程阻塞的信号时, 如果信号的动作是默认动作和捕获信号, 则下列情形发生
之前, 信号保持挂起:
* 进程解开信号的阻塞
* 改变动作为忽略
===============================================================================
===============================================================================
#include <signal.h>
int sigemptyset (sigset_t *set);
int sigfillset (sigset_t *set);
int sigaddset (sigset_t *set, int signum);
int sigdelset (sigset_t *set, int signum);
int sigismember (const sigset_t *set, int signum);
-------------------------------------------------------------------------------
上述函数的一种实现:
#define sigemptyset (ptr) ( *(ptr) = 0 )
#define sigfillset (ptr) ( *(ptr) = ~(sigset_t)0, 0 )
/* C 语言的逗号运算符: 返回右边的值作为表达式的返回值 */
#include <signal.h>
#include <errno.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);
}
===============================================================================
===============================================================================
#include <signal.h>
int sigaction (int signum, const struct sigaction *act, struct sigaction *oldact);
int sigprocmask (int how, const sigset_t *set, sigset_t *oldset);
int sigpending (sigset_t *set);
int sigsuspend (const sigset_t *mask);
-------------------------------------------------------------------------------
struct sigaction {
void (*sa_handler) (int);
void (*sa_sigaction) (int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); // 废弃的元素, 不应使用
}
-------------------------------------------------------------------------------
sigaction:
* sigaction 用于改变进程在接收到信号时的动作.
* sigaction 可指定除 SIGKILL 和 SIGSTOP 之外的信号的动作 (act->sa_handler),
可取 SIG_DFL, SIG_IGN 和用户定义函数.
* sigaction 可指定在处理 signum 信号时, 应该阻塞的信号集 (act->sa_mask).
* sigaction 可指定信号处理过程中的行为 (act->sa_flags), 下述标志 "或" 的结果:
o SA_NOCLDSTOP: 子进程停止时不接收 SIGCHLD.
o SA_ONESHOT 或 SA_RESETHAND: 重置信号动作为默认值.
o SA_RESTART: 如果该信号中断慢系统调用, 则重新启动系统调用.
o SA_NOMASK 或 SA_NODEFER: 不要避免在信号处理函数中接收同一信号.
o SA_SIGINFO: 信号处理函数接受三个参数. 这时, 必须设置 act->sa_sigaction
元素, 其中 siginfo_t 是内核传递到信号处理函数中的发生信号时进程的状态
信息. 详细信息, 可参阅 sigaction(2) 手册页.
* oldact 非空时, 可返回先前的设置.
* 利用 SA_SIGINFO 和 siginfo_t 实现有效的存储管理.
-------------------------------------------------------------------------------
sigprocmask:
* sigprocmask 用于改变进程的当前阻塞信号集.
* how 可取 SIG_BLOCK, SIG_UNBLOCK 和 SIG_MASKSET. 前两个动作分别在当前阻塞
信号集中添加或删除由 set 指定的信号集, SIG_MASK 用于完全设置阻塞信号集.
* oldset 非空时, 可返回先前的设置.
-------------------------------------------------------------------------------
sigpending:
* sigpending 用于检验挂起的信号.
-------------------------------------------------------------------------------
sigsuspend:
* sigsuspend 用于在接收到某个信号之前, 临时用 mask 替换进程的信号掩码, 并
暂停进程执行.
* sigsuspend 返回后将恢复调用之前的信号掩码.
* 该系统调用始终返回 -1, 并将 errno 设置为 EINTR.
* 该系统调用实际是阻塞并暂停两个动作的原子操作.
===============================================================================
===============================================================================
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
static void sig_int (int);
void err_sys (const char* info)
{
perror (info);
exit (1);
}
void pr_mask (const char* str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* this function may be called by signal handler */
if (sigprocmask (0, NULL, &sigset) < 0)
err_sys ("sigprocmask error");
printf ("%s", str);
if (sigismember (&sigset, SIGINT)) printf ("SIGINT ");
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, zeromask;
if (signal (SIGINT, sig_int) == SIG_ERR)
err_sys ("signal (SIGINT) error");
sigemptyset (&zeromask);
sigemptyset (&newmask);
sigaddset (&newmask, SIGINT);
/* block SIGINT and save current signal mask */
if (sigprocmask (SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys ("SIG_BLOCK error");
/* critical region of code */
pr_mask ("in critical region: ");
/* allow all signals and pause */
if (sigsuspend (&zeromask) != -1)
err_sys ("sigsuspend error");
pr_mask ("after return from sigsuspend: ");
/* reset signal mask whick unblocks SIGINT */
if (sigprocmask (SIG_SETMASK, &oldmask, NULL) < 0)
err_sys ("SIG_SETMASK error");
/* and continue processing ... */
exit (0);
}
static void sig_int (int signo)
{
pr_mask ("\nin sig_int: ");
return;
}
-------------------------------------------------------------------------------
* 在 Linux 下, 必须包含头文件:
#include <bsd/signal.h>
以便使用可靠的 signal 函数. 或者使用 sigaction 函数.
===============================================================================
===============================================================================
#include <setjmp.h>
int sigsetjmp (sigjmp_buf env, int savesigs);
void siglongjmp (sigjmp_buf env, int val);
-------------------------------------------------------------------------------
* 如果 savesigs 非零, 则 siglongjmp 在添转之后将恢复保存的信号掩码.
===============================================================================
![]()