c - 检查备用信号堆栈(不同的分配方式)

标签 c linux signals bionic

我正在尝试替代信号堆栈(man sigaltstack)。

两段代码以不同的方式分配堆栈:

int method1(void)
{
    struct sigaction act, oldact;

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = SignalHandler;
    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
        ALOGW("sigaction failed %s\n", strerror(errno));
        return -errno;
    }

    return 0;
}

我在注册信号时只是使用了 SA_ONSTACK 。当信号线程正在调度时,在 pthread_create 中,如果设置了此标志,则会分配 8kb 的堆栈,如下所示 (SIGSTKSZ = 0x2000(8kb)):

  ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  if (ss.ss_sp != MAP_FAILED) {
    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    sigaltstack(&ss, NULL);
    thread->alternate_signal_stack = ss.ss_sp;
  }

在注册信号处理程序时执行相同操作的另一种方法。

int method2(void)
{
    struct sigaction act, oldact;
    stack_t ss;

    ss.ss_sp = malloc(SIGSTKSZ);
    if (ss.ss_sp == NULL)
        return -ENOMEM;

    ss.ss_size = SIGSTKSZ;
    ss.ss_flags = 0;
    sigaltstack(&ss, NULL);

    memset(&act, 0, sizeof(act));
    act.sa_sigaction = SignalHandler;
    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
        ALOGW("sigaction failed %s\n", strerror(errno));
        return -errno;
    }

    return 0;
}

在这种情况下,我不依赖 Bionic 来分配默认堆栈。我正在分配自己的堆栈并使用它。

因此,在这两种情况下,我都分配 8kb 的信号堆栈。

我在信号处理程序中放置了一个 while(1) ,并在向进程发送信号后检查了 proc/pid/maps

结果如下:

方法一(pthread_create中bionic分配的栈):

7faa8d1000-7faa8d3000 rw-p 00000000 00:00 0        [stack:6633]

方法2(应用程序使用malloc分配堆栈):

7fb7300000-7fb7500000 rw-p 00000000 00:00 0        [stack:6567]

奇怪的是,虽然我在 method2 中使用 malloc() 只分配了 8kb 堆栈,但堆栈似乎分配了大约 2MB(0x200000)。

请就问题所在或预期行为向我提出建议。

最佳答案

我曾见过 procfs 中有关堆栈的信息不正确的情况。尝试在信号处理程序中打印局部变量的地址。我敢打赌,您会发现您看到的堆栈是主堆栈。

我不知道为什么会发生这种情况,但看起来这是一个内核问题。我在 Linux 上也看到过。

关于c - 检查备用信号堆栈(不同的分配方式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29761742/

相关文章:

c - 在 Keil uVision 中使用 STM32F429 探索板的 IIR 低通滤波器

c - 在下面的代码中 fork 后发送信号有什么问题

java - 安卓类库

c - 如何在 System() 命令中使用字符串

c - netfilter转发钩子(Hook)点修改数据包

gdb - 使用调试器停止 iff

c - 默认的 SIGINT 处理程序是如何在它的库定义中实现的?

linux - 如何在 "glibc detected *** free(): invalid pointer"上强制中止

c - 为什么 ntimes 不在子进程中添加一个?

mysql - 通过 Structured Con 在 C/MySQL 中的 SegFaults