signal
信号
信号的位置:/usr/include/signal.h
信号的分类
- 标准信号/不可靠信号:信号标识符1-32,不处于信号队列中,只能接收一次
- 实时信号/可靠信号:信号标识符32-64,同一信号可以发送多次,被多次接收,存储在sigqueue中
信号的特点
不可预测/随机性
传送数据简单,信号描述符
信号的状态
generation
delivery
信号的产生
- 键盘快捷键
- 系统调用函数
- 内核产生:硬件异常,被除数为0
信号可以由线程产生,也可以由内核产生,但内核产生的终止信号通常是致命的
信号的响应
默认:SIG_DEF通常是终止
忽略:SIG_IGN
用户自定义
==SIGKILL和SIGSTOP的默认行为不能修改,不能被忽略==
内核在信号中扮演的角色
当操作系统从内核态切换为用户态时,会检测==pending&~blocked==位图,如果位图置1则执行信号处理程序
多线程程序中的信号处理函数
对于多线程程序,kill函数会把信号传给每一个线程,当只有一个线程会执行信号处理函数
信号描述符
进程
- 记录信号是否被接受pending
- 记录屏蔽什么信号block
1 | /*进程描述符*/ |
sighand信号处理
1 | /*信号处理函数*/ |
进程task_struct
包含成员sighand_struct
,成员sighangd_struct包含一个64位的数组
其中k_sigaction是仅内核可见的部分
未决信号集
1 | /*sigset_t:64位的位图*/ |
信号屏蔽字blocked和未决信号集pending都是sig_set(64位的位图),使用unsigned int[2]表示
可靠信号多次发送后,会存储在未决信号链sigqueue中,双向链表节点存放着64位的信号位图
共享未决信号集和私有未决信号集
信号结构
1 | struct signal_struct { |
signal_struct被同一线程组所共享
信号相关调用
用户级别的系统调用
Kill
kill
:向进程发送信号
1 |
|
pid | ||
---|---|---|
pid>0 | sent to the process with the ID specified by pid. | 给指定pid的线程发送信号 |
pid=0 | sent to every process in the process group of the calling process | 给当前进程所在进程组的其他进程发送信号 |
pid=-1 | sent to every process for which the calling process has permission to send signals, except for process 1 | 给允许接受当前进程发送的信号的进程发送信号,init进程除外 |
pid<-1 | sent to every process in the process group whose ID is -pid. | 给进程号为-pid的进程发送信号 |
返回值:成功返回0,失败返回-1
error
error | explain |
---|---|
EINVAL | 无效信号值(invalid) |
EPERM | 无权限发送(permission) |
ESRCH | 目标进程不存在(search) |
signal
signal
:设置信号的处理程序
1 |
|
1 | void ( *signal(int signum, void (*handler)(int)) ) (int); |
signal在不同unix版本中实现并不相同,signal更适合将信号的处理程序设置为忽略或则默认行为,建议使用sigaction
替代signal
返回值:返回之前信号执行程序的返回值或者SIG_ERR
sigaction
sigaction
:检测或修改信号处理程序
sigaction可携带siginfo,拥有更多的信息
1 |
|
1 | struct sigaction { |
在一些体系中,sa_handler和sa_sigaction可能是共用体
通常,信号程序函数不使用第三个参数。
sa_flag的取值
SA_NOCLDSTOP | If signum is SIGCHLD,do not receive notification when child processes stop | 子进程结束后父进程不收到信号 |
SA_NOCLDWAIT | If signum is SIGCHLD, do not transform children into zombies when they terminate. | 父进程结束,子进程不变成僵尸态 |
SA_NODEFER | Do not add the signal to the thread’s signal mask while the handler is executing, unless the signal is specified in act.sa_mask. | |
SA_ONSTACK | Call the signal handler on an alternate signal stack provided by sigaltstack(2). | 为函数指定栈空间 |
SA_RESETHAND | Restore the signal action to the default upon entry to the signal handler. | 恢复默认信号处理函数 |
SA_SIGINFO | The signal handler takes three arguments | 让hander强制接受三个参数,即使用sa_action |
siginfo_t
1 | siginfo_t { |
返回值:成功返回0,失败返回-1
pause
等待一个信号的到来
abort
alarm
定时发送,被打断剩余时间会存起来
sleep
nanosleep
sigprocmask
sigsupen
信号集处理函数
sigaddset
sigfillset
sigaddsetmask
sigdelsetmask
sigemptyset
sigismember