将堆栈内存分配给线程

时间:2013-07-02 17:43:39

标签: c multithreading memory memory-management

我正在使用setjmp()和longjmp()在c中编写多线程环境以在线程之间切换。

我不确定如何最好为每个线程分配堆栈空间。这必须在更大规模的线程环境中动态完成,但我想不出一种方法来跟踪线程使用多少堆栈以改变分配的数量。

我可以预先在堆栈的各个部分之间分配一个静态的空间,如下所示:

void call_with_cushion (void) {
    char space[1000]; 
    space[999] = 1; /* Do not optimize array out of existence */
    child();
}

(来自维基百科http://en.wikipedia.org/wiki/Setjmp.h的代码段)

但这似乎超出了不灵活性,我只是想知道多线程环境通常如何为每个线程分配内存?

由于

2 个答案:

答案 0 :(得分:4)

通常,在创建线程时,分配给线程的最大堆栈空间量是固定的,如果线程超出此限制,则结果是未定义的行为 - 没有办法将堆栈空间增加到超出该限制。如果你很幸运,堆栈溢出将导致某种堆栈溢出异常或信号(取决于操作系统和线程实现),但不能保证。

如果您正在尝试实现自己的线程库,理想情况下您要为每个线程的堆栈分配大量地址空间,并设置VM系统以根据需要在该空间中分配内存,以及空间充满时陷阱。这就是大多数操作系统级别的线程库(如pthreads或win32线程)所做的事情,但VM管理的细节很棘手。

如果你不想搞乱VM的东西,你可以为每个线程堆栈分配一个比你想象的更大的堆,然后选择探测代码中的堆栈指针来查看如果它接近满(使用比你想象的更多的空间)和陷阱/中止,如果是这样的话。根据您的编译器,可以选择让它在您可以使用的每个函数中自动生成堆栈溢出检查。

维基百科页面上的代码非常糟糕 - 它可能会起作用,但是不会进行任何检查以确保有足够的堆栈空间,并且依赖于编译器不会对未定义的行为执行奇怪的操作事情(例如优化掉未使用的堆栈填充space,即使使用赋值也可以执行此操作)。

答案 1 :(得分:0)

通过堆栈操作进行任务切换通常相当容易,但setjmp / longjmp不是用于此目的的适当工具,除非您可以操作jmp_buff的内部结构。瞬间代码退出执行setjmp的上下文,由此创建的twas的jmp_buff变为无效,并且任何对它执行任何操作的尝试都将导致未定义的行为,即使您希望没有任何干扰堆栈区域的情况也是如此setjmp已经完成。

研究您正在使用的处理器的ABI(应用程序二进制接口)规则,并学习足够的汇编语言来执行一些基本的寄存器操作。您可能不需要超过1-2行的汇编代码,但您很可能需要一些代码。如果您使用任何类型的异常处理框架,那将尤其如此。