首页 > 代码库 > APUE:信号

APUE:信号

信号是系统用来异步通知一个进程某些事件发生了的机制。从效果上来说,有点像中断。信号发生时,打断原有执行过程,进入信号处理函数(如果注册了的话)或默认处理(忽略或终止程序),结束后恢复原有流程。默认情况下,信号处理过程中可能会被其它信号继续中断,所以需要考虑各种可能的情况,比如库函数重入的问题。信号处理函数执行的上下文是在原有栈帧基础上继续的,所以可以用 setjmp() 和 longjmp()。

 

一些常见的信号

  • SIGABRT
  • SIGALRM
  • SIGCHLD
  • SIGINT
  • SIGQUIT
  • SIGSEGV
  • SIGUSR1
  • SIGUSR2

 

注册信号处理函数

typedef void (*__sighandler_t) (int);
__sighandler_t signal (int __sig, __sighandler_t __handler); struct sigaction { union { /* Used if SA_SIGINFO is not set. */ __sighandler_t sa_handler; /* Used if SA_SIGINFO is set. */ void (*sa_sigaction) (int, siginfo_t *, void *); } __sigset_t sa_mask; int sa_flags; }; int sigaction (int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact);

 

信号处理函数

#define SIG_ERR	((__sighandler_t) -1)		/* Error return.  */
#define SIG_DFL	((__sighandler_t) 0)		/* Default action.  */
#define SIG_IGN	((__sighandler_t) 1)		/* Ignore signal.  */

 

产生信号

int kill (__pid_t __pid, int __sig);
int raise (int __sig);
unsigned int alarm (unsigned int __seconds);
void abort (void);

int sigqueue (__pid_t __pid, int __sig, const union sigval __val);

 

信号集

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);

 

更多函数

// 进程阻塞直到有信号产生
int pause (void);

// 阻塞信号
int sigprocmask (int __how /* = SIG_BLOCK or SIG_UNBLOCK or SIG_SETMASK */, const sigset_t *__restrict __set, sigset_t *__restrict __oset);
// 获得未决(已产生但未递送)信号
int sigpending (sigset_t *__set);

// 修改信号屏蔽字然后阻塞直到有信号产生
// 与 sigprocmask() + pause() 相比,是原子操作
int sigsuspend (const sigset_t *__set);

 

sigsetjmp() 和 siglongjmp()

#define sigsetjmp(env, savemask)	__sigsetjmp (env, savemask)
void siglongjmp (sigjmp_buf __env, int __val);

与 setjmp() 和 longjmp() 相比,如果 savemask 不为 0,使用 siglongjmp() 跳出信号处理函数时会恢复信号屏蔽字。

 

中断的系统调用

ioctl()、read()、readv()、write()、writev() 针对低速设备(可能会被永远阻塞,如管道、终端、网络等)时可能会被信号打断,如果使用 sigaction() 设置信号处理函数并指定 SA_RESTART 时会重新启动,否则返回 -1 并设置 errno 为 EINTR。

 

其它概念

  • 要注意不可靠的信号,比如在安装信号处理函数后与调用等待函数之间,信号可能会发生。
  • 必须注意可重入函数,尤其是 malloc()、free() 等

APUE:信号