Linux编码异常信号

本文介绍了Linux系统中常见的信号及其默认处理动作,如SIGHUP、SIGINT等,并提供了一个使用sigaction和backtrace功能捕获信号并在崩溃时打印堆栈信息的C++示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux支持的信号列表如下(很多信号是与机器的体系结构相关的)

信号值    默认处理动作    发出信号的原因

SIGHUP 1 A 终端挂起或者控制进程终止

SIGINT 2 A 键盘中断(如break键被按下)

SIGQU99v 3 C 键盘的退出键被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)发出的退出指令

SIGFPE 8 C 浮点异常

SIGKILL 9 AEF Kill信号

SIGSEGV 11 C 无效的内存引用

SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道

SIGALRM 14 A 由alarm(2)发出的信号

SIGTERM 15 A 终止信号

SIGUSR1 30,10,16 A 用户自定义信号1

SIGUSR2 31,12,17 A 用户自定义信号2

SIGCHLD 20,17,18 B 子进程结束信号

SIGCONT 19,18,25 进程继续(曾被停止的进程)

SIGSTOP 17,19,23 DEF 终止进程

SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键

SIGTTIN 21,21,26 D 后台进程企图从控制终端读

SIGTTOU 22,22,27 D 后台进程企图从控制终端写

处理动作一项中的字母含义如下

A 缺省的动作是终止进程

C 缺省的动作是终止进程并进行内核映像转储(dump core),内核映像转储是指将进程数据在内存的映像和进程在内核结构中的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。

E 信号不能被捕获

F 信号不能被忽略



#pragma once

#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <cxxabi.h>
#include <map>
#include <string>
#include <iostream>
#include <sstream>
#include "glog/logging.h"

const std::map<int, std::string> Signals = {     
    {SIGBUS, "SIGBUS"},  
    {SIGFPE, "SIGFPE"},    
    {SIGILL, "SIGILL"},   
    {SIGSEGV, "SIGSEGV"} 
};

static void sigHandler(int signum, siginfo_t *info, void *ctx);
void InitCrashMonitor()
{
    struct sigaction action; 
    sigemptyset(&action.sa_mask); 
    action.sa_sigaction = &sigHandler; 
    action.sa_flags = SA_SIGINFO;  
    
    for (const auto &sigPair : Signals) 
    { 
        if (sigaction(sigPair.first, &action, NULL) < 0) 
            fprintf(stderr, "Error: sigaction failed! \n"); 
    }
}

static void sigHandler(int signum, siginfo_t *info, void *ctx) 
{ 
    const size_t dump_size = 50; 
    void *array[dump_size]; 
    int size = backtrace(array, dump_size); 
    char **symbols = backtrace_symbols(array, size); 
    std::ostringstream oss; 
 
    for (int i = 0; i < size; ++i) 
    { 
        char *mangleName = 0; 
        char *offsetBegin = 0; 
        char *offsetEnd = 0; 
 
        for (char *p = symbols[i]; *p; ++p) 
        { 
            if ('(' == *p) 
            {    
                 mangleName = p; 
            }    
            else if ('+' == *p) 
            { 
                offsetBegin = p; 
            } 
            else if (')' == *p) 
            { 
                offsetEnd = p; 
                break; 
            } 
        } 
 
        if (mangleName && offsetBegin && offsetEnd && mangleName < offsetBegin) 
        { 
            *mangleName++ = '\0'; 
            *offsetBegin++ = '\0'; 
            *offsetEnd++ = '\0'; 
             
            int status; 
            char *realName = abi::__cxa_demangle(mangleName, 0, 0, &status); 
            if (0 == status) 
                oss << "\tstack dump [" << i << "]  " << symbols[i] << " : " << realName << "+" ; 
            else 
                oss << "\tstack dump [" << i << "]  " << symbols[i] << mangleName << "+"; 
            oss << offsetBegin << offsetEnd << std::endl; 
            free(realName); 
        } 
        else 
        { 
            oss << "\tstack dump [" << i << "]  " << symbols[i] << std::endl; 
        } 
    } 
    free(symbols); 
    LOG(ERROR) << oss.str(); // 打印函数调用栈信息 
    exit(0);
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏马潜行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值