信号提供一种机制,告诉用户进程发生了那些异常。
编号 | 信号名称 | 缺省动作 | 说明 |
---|---|---|---|
1 | SIGHUP | 终止 | 终止控制终端或进程 |
2 | SIGINT | 终止 | 键盘产生的中断(Ctrl-C) |
3 | SIGQUIT | dump | 键盘产生的退出 |
4 | SIGILL | dump | 非法指令 |
5 | SIGTRAP | dump | debug中断 |
6 | SIGABRT/SIGIOT | dump | 异常中止 |
7 | SIGBUS/SIGEMT | dump | 总线异常/EMT指令 |
8 | SIGFPE | dump | 浮点运算溢出 |
9 | SIGKILL | 终止 | 强制进程终止 |
10 | SIGUSR1 | 终止 | 用户信号,进程可自定义用途 |
11 | SIGSEGV | dump | 非法内存地址引用 |
12 | SIGUSR2 | 终止 | 用户信号,进程可自定义用途 |
13 | SIGPIPE | 终止 | 向某个没有读取的管道中写入数据 |
14 | SIGALRM | 终止 | 时钟中断(闹钟) |
15 | SIGTERM | 终止 | 进程终止 |
16 | SIGSTKFLT | 终止 | 协处理器栈错误 |
17 | SIGCHLD | 忽略 | 子进程退出或中断 |
18 | SIGCONT | 继续 | 如进程停止状态则开始运行 |
19 | SIGSTOP | 停止 | 停止进程运行 |
20 | SIGSTP | 停止 | 键盘产生的停止 |
21 | SIGTTIN | 停止 | 后台进程请求输入 |
22 | SIGTTOU | 停止 | 后台进程请求输出 |
23 | SIGURG | 忽略 | socket发生紧急情况 |
24 | SIGXCPU | dump | CPU时间限制被打破 |
25 | SIGXFSZ | dump | 文件大小限制被打破 |
26 | SIGVTALRM | 终止 | 虚拟定时时钟 |
27 | SIGPROF | 终止 | profile timer clock |
28 | SIGWINCH | 忽略 | 窗口尺寸调整 |
29 | SIGIO/SIGPOLL | 终止 | I/O可用 |
30 | SIGPWR | 终止 | 电源异常 |
31 | SIGSYS/SYSUNUSED | dump | 系统调用异常 |
int sigaction(int signum, // 信号量
const struct sigaction *act, // 设置对信号量新的处理方式
struct sigaction *oldact); // oldact如果非空,会将原来的信号量处理方式保存到oldact
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t*, void*);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
sa_handle, 指定信号捕捉后的处理函数名(即注册函数)。也可赋值为
sa_sigaction, 如果sa_flags 设置了SA_SIGINFO, sa_sigaction可以替代sa_handle指定信号捕捉后处理函数名(即注册函数)
sa_flags, 修改信号行为的标志
sa_mask, 调用信号处理函数时,所要屏蔽的信号集合
sa_restorer, 为了返回旧的信号处理程序,但现在应该是已经弃用了
SA_ONSTACK 在信号处理程序的执行期间使用备用信号堆栈。[1,2]
Here is one example…a process has a limit on the size of the stack. If a process exceeds that limit it will get a signal, often SIGSEGV, but it can vary from os to os. Now, how can you catch that signal? Without an alternate stack, the signal handler could never run.
I had this exact situation once. A process was dying from a blown stack but its current directory was in a filesystem that was too small to hold a core dump. My handler needed to catch the signal, cd to a large filesystem, set the signal action back to default, and resend the signal to itself. I could not have done that without an alternate stack.
That was the only time that I needed an alternate stack.
SA_RESTART, 当信号处理函数返回后, 被该信号中断的系统调用将自动恢复.[3]
SA_SIGINFO, sa_sigaction可以替代sa_handle指定信号捕捉后处理函数名(即注册函数)
typedef struct {
int si_signo;
int si_code;
union sigval si_value;
int si_errno;
pid_t si_pid;
uid_t si_uid;
void *si_addr;
int si_status;
int si_band;
} siginfo_t;
int sigaddset(sigset_t *set, int signum);
typedef struct {
unsigned long sig[_NSIG_WORDS];
} sigset_t
int sigemptyset(sigset_t *set)
将参数set信号集初始化并清空
屏蔽某个线程对某些信号的 响应处理
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
How:
SIG_BLOCK: 结果集是当前集合参数集的并集
SIG_UNBLOCK: 结果集是当前集合参数集的差集
SIG_SETMASK: 结果集是由参数集指向的集
int sigfillset(sigset_t *set);
set指向的信号集中将包含linux支持的信号量
int sigdelset(sigset_t *set, int signum);
在set指向的信号集中删除signum信号
// ucontext.h
typedef struct ucontext {
unsigned long int uc_flags;
struct ucontext *uc_link; // 指向一个上下文,当当前上下文结束时,将返回执行该上下文
stack_t uc_stack; // 栈信息
mcontext_t uc_mcontext; // 保存上下文的各种寄存器信息
__sigset_t uc_sigmask; // 屏蔽的信号量集合
struct _libc_fpstate __fpregs_mem;
} ucontext_t;
typedef struct {
void *ss_sp; // 栈空间指针,指向当前栈所在的位置
int ss_flags; // 栈空间的flags
size_t ss_size; // 整个栈的大小
} stack_t;