signal()函数的使用及小结

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专用,进程超过资源限制的时候发

猜你喜欢

转载自blog.csdn.net/reasonyuanrobot/article/details/113590211
今日推荐