APUE:信號
阿新 • • 發佈:2017-05-26
queue 繼續 重新 情況 操作 setjmp cti -1 系統
信號是系統用來異步通知一個進程某些事件發生了的機制。從效果上來說,有點像中斷。信號發生時,打斷原有執行過程,進入信號處理函數(如果註冊了的話)或默認處理(忽略或終止程序),結束後恢復原有流程。默認情況下,信號處理過程中可能會被其它信號繼續中斷,所以需要考慮各種可能的情況,比如庫函數重入的問題。信號處理函數執行的上下文是在原有棧幀基礎上繼續的,所以可以用 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:信號