Signal ()函数用法和总结 https://www.cnblogs.com/wuyepeng/p/9790396.html
Linux C++应用程序退出时的事件响应 https://blog.csdn.net/fk2016/article/details/83381246
void(* signal(int sig,void(* func)(int)))(int);
使用示例1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
typedef void (*signal_handler)(int);
void signal_routine(int sig)
{
switch (sig)
{
case 1:
{
printf(">>: SIGHUP \r\n");
break;
}
case 2:
{
printf(">>: SIGINT \r\n");//"ctrl+c"
break;
}
case 3:
{
printf(">>: SIGQUIT \r\n");//"ctrl+\""
break;
}
case 15:
{
printf(">>: SIGTERM \r\n");
break;
}
}
printf("killing on exit ! \r\n");
exit(0);
return;
}
int main(void)
{
signal_handler sig_handler = signal_routine;
signal(SIGHUP, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGQUIT, sig_handler);
signal(SIGTERM, sig_handler);
while(true)
{
int a = 1 + 1;
}
return 0;
}
示例2:
class ExitExpection
{
public:
ExitExpection(){};
~ExitExpection(){};
};
void signal_routine(int sig)
{
switch (sig)
{
case 1:
{
printf(">>: SIGHUP \r\n");
break;
}
case 2:
{
printf(">>: SIGINT \r\n");//"ctrl+c"
break;
}
case 3:
{
printf(">>: SIGQUIT \r\n");//"ctrl+\""
break;
}
case 15:
{
printf(">>: SIGTERM \r\n");
break;
}
}
const ExitExpection e;
throw(e);
// printf(">>: killing on exit ! \r\n");
// exit(0);
}
int main()
{
signal(SIGHUP, signal_routine);
signal(SIGINT, signal_routine);
signal(SIGQUIT, signal_routine);
signal(SIGTERM, signal_routine);
try
{
/**
* do something
*
* */
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n'<< endl;
}
catch(const ExitExpection& e)
{
/**
* do something
*
* */
printf(">>: killing on exit ! \r\n");
exit(0);
}
}
exit()函数
exit()函数定义在stdlib.h中,而_exit()定义在unistd.h中
_exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。
exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是”清理I/O缓冲”。
exit()在结束调用它的进程之前,要进行如下步骤:
1.调用atexit()注册的函数(出口函数);按ATEXIT注册时相反的顺序调用所有由它注册的函数,这使得我们可以指定在程序终止时执行自己的清理动作.例如,保存程序状态信息于某个文件,解开对共享数据库上的锁等.
2.cleanup();关闭所有打开的流,这将导致写所有被缓冲的输出,删除用TMPFILE函数建立的所有临时文件.
3.最后调用_exit()函数终止进程
exit(0)表示正常退出;传入的参数是程序退出时的状态码,0表示正常退出,其他表示非正常退出,一般都用-1或者1;
exit(0)时,并不会自动执行类的析构函数;
小结:
1. 对ctrl+c写一signal_handler,使得关闭终端时,抛出自定义异常,在try-catch模块执行class的析构函数,并打印提示信息,最后调用exit(0)函数, 如示例2;
2.signal(SIGCHLD, SIG_IGN)解析 https://blog.csdn.net/u013246898/article/details/52985739
处理僵尸进程。忽略SIGCHLD信号,内核将把僵尸进程交由init进程去处理,能够省去大量僵尸进程占用系统资源。
3.signal(SIGPIPE, SIG_IGN)解析 https://blog.csdn.net/weixin_33841722/article/details/92183262
SIGPIPE错误是指,当对端关闭时,而本端并不知情,仍然保持该连接,并向对端写数据,第一次会收到RST,第二次再写则是SIGPIPE信号。你的客户端关闭了,但是服务端仍然在向客户端写数据,因此会产生SIGPIPE信号,该信号默认动作是终止进程。
采用 signal(SIGPIPE,SIG_IGN);忽略该信号。
一些常用的Signal :
Signal | Description |
SIGABRT | 由调用abort函数产生,进程非正常退出 |
SIGALRM | 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时 |
SIGBUS | 某种特定的硬件异常,通常由内存访问引起 |
SIGCANCEL | 由Solaris Thread Library内部使用,通常不会使用 |
SIGCHLD | 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略 |
SIGCONT | 当被stop的进程恢复运行的时候,自动发送 |
SIGEMT | 和实现相关的硬件异常 |
SIGFPE | 数学相关的异常,如被0除,浮点溢出,等等 |
SIGFREEZE | Solaris专用,Hiberate或者Suspended时候发送 |
SIGHUP | 发送给具有Terminal的Controlling Process,当terminal 被disconnect时候发送 |
SIGILL | 非法指令异常 |
SIGINFO | BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程 |
SIGINT | 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程 |
SIGIO | 异步IO事件 |
SIGIOT | 实现相关的硬件异常,一般对应SIGABRT |
SIGKILL | 无法处理和忽略。中止某个进程 |
SIGLWP | 由Solaris Thread Libray内部使用 |
SIGPIPE | 在reader中止之后写Pipe的时候发送 |
SIGPOLL | 当某个事件发送给Pollable Device的时候发送 |
SIGPROF | Setitimer指定的Profiling Interval Timer所产生 |
SIGPWR | 和系统相关。和UPS相关。 |
SIGQUIT | 输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程 |
SIGSEGV | 非法内存访问 |
SIGSTKFLT | Linux专用,数学协处理器的栈异常 |
SIGSTOP | 中止进程。无法处理和忽略。 |
SIGSYS | 非法系统调用 |
SIGTERM | 请求中止进程,kill命令缺省发送 |
SIGTHAW | Solaris专用,从Suspend恢复时候发送 |
SIGTRAP | 实现相关的硬件异常。一般是调试异常 |
SIGTSTP | Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程 |
SIGTTIN | 当Background Group的进程尝试读取Terminal的时候发送 |
SIGTTOU | 当Background Group的进程尝试写Terminal的时候发送 |
SIGURG | 当out-of-band data接收的时候可能发送 |
SIGUSR1 | 用户自定义signal 1 |
SIGUSR2 | 用户自定义signal 2 |
SIGVTALRM | setitimer函数设置的Virtual Interval Timer超时的时候 |
SIGWAITING | Solaris Thread Library内部实现专用 |
SIGWINCH | 当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程 |
SIGXCPU | 当CPU时间限制超时的时候 |
SIGXFSZ | 进程超过文件大小限制 |
SIGXRES | Solaris专用,进程超过资源限制的时候发 |