检查备用信号堆栈(分配它的不同方法)

时间:2015-04-21 02:18:33

标签: 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;
}

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

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

我在信号处理程序中添加了while(1),并在向流程发送信号后检查了proc/pid/maps

结果如下:

方法1(由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]

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

请告诉我出了什么问题或是预期的行为。

1 个答案:

答案 0 :(得分:0)

我已经看过procfs中有关堆栈的信息不正确的时候了。尝试在信号处理程序中打印局部变量的地址。我敢打赌,你会发现你看到的堆栈是主堆栈。

我不知道为什么会这样,但它看起来像是一个内核的东西。我也在Linux上看过它。