Linux系列signal函数详解
Posted 飞翔的鲲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux系列signal函数详解相关的知识,希望对你有一定的参考价值。
Date: 2023.1.18
文章目录
转载自:http://imhuchao.com/2300.html
signal作用是为信号注册一个处理器。这里的“信号”是软中断信号,这种信号来源主要有三种:
程序错误:比如除0,非法内存访问。
外部信号:终端Ctrl-C产生的SIGINT信号,定时器产生的SIGALERM。
显示请求:kill函数发送的任意信号。
当kill一个进程的时候,默认会发送SIGTERM信号,此时这个信号只有默认处理操作(SIG_DFL),直接中断进程执行。如果此时该进程正在执行一个任务,直接终止该进程会导致任务没有完成。这个时候为SIGTERM信号注册一个信号处理函数就十分有必要。
1、介绍
typedef void (*sighandler_t) (int);
sighandler_t signal (int sig, sighandler_t handler)
参数:
sig | 要设置信号处理函数的信号。它可以是实现定义值或下例值之一: |
---|---|
SIGABRT | |
SIGFPE | |
SIGILL | |
SIGINT | |
SIGSEGV | |
SIGTERM | |
定义信号类型 (宏常量) |
handler 信号处理函数。这必须是下列之一:SIG_DFL 宏。信号处理函数被设为默认信号处理函数。SIG_IGN 宏。忽略信号。指向函数指针。函数签名必须等价于如下:extern “C” void fun(int sig);
返回值:成功时为先前的信号处理函数,失败时为 SIG_ERR (某些实现上能禁用设置信号处理函数)。
使用:使用方法请直接看下面的例子。注册一个信号用于在按下Ctrl-C时不立刻终止进程,而是输出一段文字并sleep一段时间。
#include <signal.h>
#include <unistd.h>
#include <iostream>
bool is_stop = false;
void quit_handler(int signo)
is_stop = true;
std::cout << "stopping\\n";
sleep(2);
int main()
auto prev = signal(SIGINT, quit_handler);
if (prev == SIG_ERR)
abort();
while (!is_stop)
std::cout << "running\\n";
sleep(1);
std::cout << "stopped\\n";
2、如何安装多个处理函数
signal只能为一个信号添加一个处理函数,添加多个处理函数时后面的函数会覆盖前面的函数。看如下代码
#include <signal.h>
#include <unistd.h>
#include <iostream>
bool is_stop = false;
void quit_handler1(int signo)
is_stop = true;
std::cout << "handler1\\n";
sleep(2);
void quit_handler2(int signo)
is_stop = true;
std::cout << "handler2\\n";
sleep(2);
int main()
auto prev1 = signal(SIGINT, quit_handler1);
auto prev2 = signal(SIGINT, quit_handler2);
if (prev1 == SIG_ERR || prev2 == SIG_ERR)
abort();
while (!is_stop)
std::cout << "running\\n";
sleep(1);
std::cout << "stopped\\n";
运行之后按下Ctrl-C,结果发现只有handler2有效,handler1失效了。
3、信号列表
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专用,进程超过资源限制的时候发 |
THE END!
以上是关于Linux系列signal函数详解的主要内容,如果未能解决你的问题,请参考以下文章