Linux信号通俗的来说也就是软中断,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
在linux中信号有下面这64个,其中信号有两种分类:
(1)可靠性方面:可靠信号与不可靠信号
信号值位于SIGRTMIN及SIGRTMAX之间
不可靠信号是信号值小于SIGRTMIN的信号
Linux下的不可靠信号问题主要指的是信号可能丢失
(2)与时间的关系上:实时信号与非实时信号
非实时信号都不支持排队,都是不可靠信号
实时信号都支持排队,都是可靠信号
规则信号
信号编号 | 名称 | 默认动作 | 说明 |
---|---|---|---|
1 | SIGHUP | 终止 | 终止控制终端或进程 |
2 | SIGINT | 终止 | 由键盘引起的终端(Ctrl-c) |
3 | SIGQUIT | dump | 控制终端发送给进程的信号, 键盘产生的退出(Ctrl-\), |
4 | GIGILL | dusmp | 非法指令引起 |
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 | 系统调用异常 |
python:
接收信号:signal.signal(sig,action)
sig为某个信号,action为该信号的处理函数
发送信号:os.kill(pid, sig)
#!/usr/bin/python3
import signal
import os
def sighandler(sig,sighandler):
if sig == signal.SIGINT:
print("recv the signal:%d"%sig)
exit(0)
elif sig == signal.SIGUSR1:
print("recv the signal:%d,so i will kill myself,byebye!"%sig)
os.kill(os.getpid(),signal.SIGTERM)
signal.signal(signal.SIGINT,sighandler)
signal.signal(signal.SIGUSR1,sighandler)
while True:
str1 = input("please input \"kill\":")
if str1 == "kill":
os.kill(os.getpid(),signal.SIGUSR1)
C:
1、int sigemptyset(sigset_t *set);
该函数的作用是将信号集初始化为空。
2、int sigfillset(sigset_t *set);
该函数的作用是把信号集初始化包含所有已定义的信号。
3、int sigaddset(sigset_t *set, int signo);
该函数的作用是把信号signo添加到信号集set中,成功时返回0,失败时返回-1。
4、int sigdelset(sigset_t *set, int signo);
该函数的作用是把信号signo从信号集set中删除,成功时返回0,失败时返回-1.
5、int sigismember(sigset_t *set, int signo);
该函数的作用是判断给定的信号signo是否是信号集中的一个成员,如果是返回1,如果不是,返回0,如果给定的信号无效,返回-1;
6、int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
该函数可以根据参数指定的方法修改进程的信号屏蔽字。新的信号屏蔽字由参数set(非空)指定,而原先的信号屏蔽字将保存在oset(非空)中。如果set为空,则how没有意义,但此时调用该函数,如果oset不为空,则把当前信号屏蔽字保存到oset中。
how 的不同取值及操作如下所示:
如果sigpromask成功完成返回0,如果how取值无效返回-1,并设置errno为EINVAL。
注意:调用这个函数才能改变进程的屏蔽字,之前的函数都是为改变一个变量的值而已,并不会真正影响进程的屏蔽字。
7、int sigpending(sigset_t *set);
该函数的作用是将被阻塞的信号中停留在待处理状态的一组信号写到参数set指向的信号集中,成功调用返回0,否则返回-1,并设置errno表明错误原因。
8、int sigsuspend(const sigset_t *sigmask);
该函数通过将进程的屏蔽字替换为由参数sigmask给出的信号集,然后挂起进程的执行。注意操作的先后顺序,是先替换再挂起程序的执行。程序将在信号处理函数执行完毕后继续执行。如果接收到信号终止了程序,sigsuspend()就不会返回,如果接收到的信号没有终止程序,sigsuspend()就返回-1,并将errno设置为EINTR。
//
// Description: 本程序阻塞除SIGKILL和SIGSTOP之外的所有信号10秒钟
// 在此期间给本程序发信号,观察效果。10秒钟之后解除
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void sighandler(int sig)
{
fprintf(stderr, "catch %d.\n", sig);
}
int main(int argc, char **argv)
{
sigset_t sigs;
sigemptyset(&sigs);
int i;
for(i=SIGHUP; i<=SIGRTMAX; i++)
{
if(i == SIGKILL || i == SIGSTOP)
continue;
signal(i, sighandler);
sigaddset(&sigs, i);
}
printf("[%d]: blocked signals for a while...\n", getpid());
sigprocmask(SIG_BLOCK, &sigs, NULL);
sleep(10);
printf("[%d]: unblocked signals.\n", getpid());
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
return 0;
}