信号处理函数默认会在进程栈创建一个栈帧,但当进程栈的大小到达了限制值的时候,进程会收到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;
}
去掉注释的执行结果:
加上注释的执行结果: