函数声明
sighandler_t signal(int signum, sighandler_t handler);
- 参数signum表示信号的编号。
- 参数handler表示信号的处理方式,有三种情况:
1)SIG_IGN:忽略参数signum所指的信号。
2)一个自定义的处理信号的函数,信号的编号为这个自定义函数的参数。
3)SIG_DFL:恢复参数signum所指信号的处理方法为默认值。 - 不用关心signal的返回值。
信号的作用
服务程序运行在后台,如果想让中止它,强行杀掉不是个好办法,因为程序被杀的时候,程序突然死亡,没有释放资源,会影响系统的稳定,用Ctrl+c中止与杀程序是相同的效果。
如果能向后台程序发送一个信号,后台程序收到这个信号后,调用一个函数,在函数中编写释放资源的代码,程序就可以有计划的退出,安全而体面。
应用示例
- 在实际开发中,在main函数开始的位置,程序员会先屏蔽掉全部的信号。
for (int ii=0;ii<100;ii++) signal(ii,SIG_IGN);
- 这么做的目的是不希望程序被干扰。然后,再设置程序员关心的信号的处理函数。
程序员关心的信号有三个:SIGINT、SIGTERM和SIGKILL。 - 程序在运行的进程中,如果按Ctrl+c,将向程序发出SIGINT信号,信号编号是2。
- 采用“kill 进程编号”或“killall 程序名”向程序发出的是SIGTERM信号,编号是15。
- 采用“kill -9 进程编号”向程序发出的是SIGKILL信号,编号是9,此信号不能被忽略,也无法捕获,程序将突然死亡。
所以,程序员只要设置SIGINT和SIGTERM两个信号的处理函数就可以了,这两个信号可以使用同一个处理函数,函数的代码是释放资源。
代码
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
using namespace std;
void inte(int sig); //必须包含一个int参数
int main()
{
for (int ii=0;ii<100;ii++) signal(ii,SIG_IGN); //屏蔽全部的信号
signal(SIGINT, SIG_IGN); //设置忽略SIGINT信号
signal(15, inte); //设置SIGTERM信号的处理函数
for (int i = 0; i < 10; i++)
{
cout << i << endl;
sleep(10);
}
}
void inte(int sig)
{
cout << "process interrupted! signal: " << sig << endl;
/*
释放资源的代码
*/
}
至此,编译运行,不能被CTRL c中断,也不能被kill -15杀死,只有kill -9能够强制停止该进程。