
前言
什么是信号?信号是给程序提供一种可以处理异步事件
的方法,它利用软件中断
来实现。不能自定义信号
,所有信号都是系统预定义的
软中断和硬中断:
1、软中断是由软件产生的中断,通常是通过软件指令(如系统调用或软中断指令)触发的,比如①系统调用②定时器中断③网络中断.........。
2、硬中断是由硬件设备发送给处理器的中断信号,用于通知处理器某个硬件设备发生了特定的事件,如硬件故障、设备输入/输出完成等,比如①键盘中断(当用户按下键盘上的按键时,硬件会触发中断通知内核,用户要输入东西)②鼠标中断.........。
信号由谁产生
1、用户输入:用户在终端中执行特定的操作,如按下 Ctrl+C 产生的 SIGINT 信号(如果没有设置处理该信号的函数的话,默认是中断该进程),表示中断操作。
2、系统调用:进程通过执行系统调用向操作系统请求某种服务时,操作系统可以产生相应的信号作为响应或通知。
3、软件异常:当进程执行出现错误或异常情况时,如除零错误、段错误等,操作系统会向进程发送相应的信号来通知异常情况。
4、定时器:操作系统可以使用定时器来触发定时事件,并产生相应的信号来通知进程。
5、其他进程发送信号:一个进程可以向另一个进程发送信号,通过信号进行进程间的通信或控制。
6、硬件事件:某些硬件设备的操作或事件,如硬盘读写完成、网络设备接收到数据等,可以触发硬件中断,从而产生相应的信号。
常见信号种类
信号分为进程接受到后会终止的信号和不会终止的信号
以下信号如果不被捕获,则进程接受到后都会终止!👇
信号名称 | 说明 |
---|---|
SIGABORT | 进程异常终止 |
SIGALRM | 超时告警 |
SIGFPE | 浮点运算异常 |
SIGHUP | 连接挂断 |
SIGILL | 非法指令 |
SIGINT | 终端中断 (Ctrl+C将产生该信号) |
SIGKILL | 终止进程 |
SIGPIPE | 向没有读进程的管道写数据 |
SIGQUIT | 终端退出(Ctrl+\将产生该信号) |
SIGSEGV | 无效内存段访问 |
SIGTERM | 终止 |
SIGUSR1 | 用户自定义信号1 |
SIGUSR2 | 用户自定义信号2 |
以下信号进程接受到后不会终止,只是特定条件下的会触发的信号!👇
信号名称 | 说明 |
---|---|
SIGCHLD | 子进程已停止或退出 |
SIGCONT | 让暂停的进程继续执行 |
SIGSTOP | *停止执行(即“暂停") |
SIGTSTP | 中断挂起 |
SIGTTIN | 后台进程尝试读操作 |
SIGTTOU | 后台进程尝试写 |
信号的种类不需要背,在项目中基本不会使用到具体信号处理,用到的时候我们再去查就好了
信号处理
信号的处理有下列三种方式:
1、忽略此信号
2、捕捉信号,指定信号处理函数进行处理
3、执行系统默认动作,大多数都是终止进程
使用函数signal函数进行设置👇
signal函数的第一个参数是信号
,第二个参数是如何处理,如果是SIG_IGN是忽略此信号
、SIG_DEF则是使用默认方法处理此信号
、也可以是自己写的一个函数(需要void类型的函数)
怎么用嘞,看下面的代码就知道了啦
忽略信号
main1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main(void)
{
//当接收到SIGINT信号(ctrl+c)时进行忽略,不处理信号
signal(SIGINT,SIG_IGN);
while (1) {
sleep(1);
}
return 0;
}
运行效果:
疯狂按ctrl+c都不会终止该进程,只能通过别的信号来终止该进程,比如kill -9 进程号
信号捕捉
信号的捕捉,就是当触发信号的时候,我们可以用自己定义的函数来处理这个信号
main1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void myhandle(int sig)
{
printf("Catch a signal : %d\n", sig);
//又变回默认信号操作了
signal(SIGINT, SIG_DFL);
}
int main(void)
{
//ctrl+c会发送SIGINT,当SIGINT触发后不再是退出进程而是触发myhandle方法,所以得手动kill进程或使用其他信号才可以结束进程
signal(SIGINT, myhandle);
while (1) {
sleep(1);
}
return 0;
}
运行结果: