APUE - 信号
信号概念
可以要求内核在某个信号出现时按照下列三种方式之一进行处理,我们称之为信号的处理或者与信号相关的动作。
- 忽略此信号。大多数信号都可使用这种方式进行处理,但有两种信号却决不能被忽略,它们是 SIGKILL 和 SIGSTOP。这两种信号不能被忽略的原因是:它们向超级用户提供了使进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号,则进程的运行行为是未定义的。
- 捕捉信号。为了做到这一点,要通知内核在某种信号发生时调用一个用户函数。在用户函数中,可执行用户希望对这种事件进行的处理。注意,不能捕捉 SIGKILL 和 SIGSTOP 信号。
- 执行系统默认动作。
signal 函数
UNIX 系统的信号机制最简单的接口是 signal 函数。
#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
kill 和 raise 函数
kill 函数将信号发送给进程或进程组。raise 函数允许进程向自身发送信号。
#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
alarm 和 pause 函数
使用 alarm 函数可以设置一个计时器,在将来某个指定的时间该计时器会超时。当计时器超时时,产生 SIGALRM 信号。如果不忽略或不捕捉此信号,则其默认动作是终止调用该 alarm 函数的进程。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
每个进程只能有一个闹钟时钟。如果在调用 alarm 时,以前已为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟时钟的余留值作为本次 alarm 函数调用的返回值。以前登记的闹钟时钟则被新值代替。
如果有以前为进程登记的尚未超过的闹钟时钟,而且本次调用的 seconds 值是 0,则取消以前的闹钟时钟,其余留值仍作为 alarm 函数的返回值。
pause 函数使调用进程挂起直至捕捉到一个信号。
#include <unistd.h>
int pause(void);
只有执行了一个信号处理程序并从其返回时,pause 才返回。
信号集
POSIX.1 定义了数据类型 sigset_t 以包含一个信号集,并且定义了下列五个处理信号集的函数。
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
sigprocmask 函数
调用 sigprocmask 函数可以检测或更改信号屏蔽字,或者在一个步骤中同时执行这两个操作。
#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set,
sigset_t *restrict oset);
sigprocmask 是仅为单线程的进程定义的。
sigpending 函数
sigpending 函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能递送,因而也一定是当前未决的。
#include <signal.h>
int sigpending(sigset_t *set);
sigaction 函数
sigaction 函数的功能是检查或修改与指定信号相关联的处理动作(或同时执行这两种操作)。
#include <signal.h>
int sigaction(int signo, const struct sigaction *restrict act,
struct sigaction *restrict oact);
struct sigaction {
void (*sa_handler)(int); /* addr of signal handler, */
/* or SIG_IGN, or SIG_DFL */
sigset_t sa_mask; /* additional signals to block */
int sa_flags; /* signal options */
/* alternate handler */
void (*sa_sigaction)(int, siginfo_t *, void *);
};
struct siginfo {
int si_signo; /* signal number */
int si_errno; /* if nonzero, errno value from <errno.h> */
int si_code; /* additional info (depends on signal) */
pid_t si_pid; /* sending process ID */
uid_t si_uid; /* sending process real user ID */
void *si_addr; /* address that caused the fault */
int si_status; /* exit value or signal number */
long si_band; /* band number for SIGPOLL */
/* possibly other fields also */
};
sigsetjmp 和 siglongjmp 函数
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);
void siglongjmp(sigjmp_buf env, int val);
sigsuspend 函数
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
abort 函数
#include <stdlib.h>
void abort(void);
sleep 函数
#include <unistd.h>
unsigned int sleep(unsigned int seconds);