zoukankan      html  css  js  c++  java
  • stack_t信号处理函数的备用栈

    信号处理函数默认会在进程栈创建一个栈帧,但当进程栈的大小到达了限制值的时候,进程会收到SIGSEGV信号,于是进程便不能创建栈帧了,所以程序就直接执行其默认行为(终止进程) 。

    为了解决这个情况,提出了一个备用栈的概念 使得栈帧在这里创建。

    操作如下:
        首先要分配一块内存,可以是静态申请的也可以是动态申请的,这个主要使用结构体 struct stack_t。

        然后使用系统调用 int sigaltstack(const stack_t *sigstack , stack_t * old_sigstack ); //头文件 signal.h

        之后创建信号处理器函数的时候将标志设置成 SA_ONSTACK ,通知内核在备选栈中创建栈帧。

    以下给出 struct stack_t 的结构体:

    typedef struct {
        void *ss_sp; // 备选栈的地址
        int ss_flags; // 各种设置掩码
        size_t ss_size; // 备选栈的大小,一般设置为宏SIGSTKSZ
    } stack_t ;

    代码示例:

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    static void Recursive()
    {
        char buffer[1000000];
        printf("buffer position : %p
    ", buffer);
        Recursive();
    }
    
    static void SignalHandler(int signal)
    {
        printf("signal : %s
    ", strsignal(signal));
        fflush(0);
        _exit(-1);
    }
    
    int main()
    {
        // stack_t signalStack;
        // signalStack.ss_flags = 0;
        // signalStack.ss_size = SIGSTKSZ;
        // signalStack.ss_sp = malloc(SIGSTKSZ);
    
        // sigaltstack(&signalStack, 0);
    
        // struct sigaction signalAction;
        // signalAction.sa_handler = SignalHandler;
        // sigemptyset(&signalAction.sa_mask);
        // signalAction.sa_flags = SA_ONSTACK;
    
        // sigaction(SIGSEGV, &signalAction, 0);
        Recursive();
        return 0;
    }

    去掉注释的执行结果:

     加上注释的执行结果:

  • 相关阅读:
    刷水题(四)
    C++如何调试
    刷水题(三)
    刷水题(二)
    虔诚的墓主人(BZOJ1227)(洛谷P2154)解题报告
    同余方程组(EXCRT)(luogu4777)
    数据结构——树状数组详解
    程序自动分析(NOI2015)(洛谷P1955)题解
    小胖的奇偶(Viojs1112)题解
    小胖守皇宫(VIJOS P1144 )题解
  • 原文地址:https://www.cnblogs.com/tongyishu/p/12194308.html
Copyright © 2011-2022 走看看