使用不同的堆栈指针(gcc)调用C函数

jexiocij  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(118)

我正在寻找一种方法来调用不同堆栈中的C函数,即保存当前堆栈指针,将堆栈指针设置为不同的位置,调用函数并在返回时恢复旧堆栈指针。
这是一个用于编程语言的轻量级线程系统。线程将在非常小的堆栈上操作,当需要更多堆栈时检查并动态调整堆栈大小。这是为了在不浪费大量内存的情况下分配数千个线程。当调用C代码时,使用小堆栈是不安全的,因为C代码不知道检查和调整大小。所以我想使用一个大的pthread堆栈,它只用于调用C(在同一个pthread上的轻量级线程之间共享)。
现在我可以写汇编代码存根,这将工作得很好,但我想知道是否有一个更好的方法来做到这一点,如gcc扩展或库已经实现了它。- )我问这个只是出于懒惰,不想重新发明轮子。

g0czyy6m

g0czyy6m1#

假设您使用的是POSIX线程,并且是在POSIX系统上,那么您可以通过信号来实现这一点。(sigaltstack)并指定一个特殊的实时信号,使其处理程序在备用信号堆栈上运行。然后raise信号切换到堆栈,并使信号处理程序读取要调用的函数的数据,以及要传递的参数,从线程本地数据。
请注意,这种方法相当昂贵(多个系统调用来更改堆栈),但应该100%可移植到POSIX系统。由于它很慢,您可能希望使用汇编编写特定于arch-call-on-alt-stack的函数,并且只使用我的通用解决方案作为您没有编写汇编版本的arch-call-on-alt-stack函数的后备。

9jyewag0

9jyewag02#

虽然在POSIX. 1 -2008中已被弃用,但您可以使用makecontext()和swapcontext():

#define _XOPEN_SOURCE 500
#include <stdio.h>                                                          
#include <ucontext.h>                                                       

void f();

int main()
{
    static char f_stack[4096];
    static ucontext_t uc_main;
    static ucontext_t uc_f;

    getcontext(&uc_f);
    uc_f.uc_stack.ss_sp = f_stack;
    uc_f.uc_stack.ss_size = sizeof f_stack;
    uc_f.uc_link = &uc_main;
    makecontext(&uc_f, f, 1, 2);  /* f1(2) */

    f(1);
    swapcontext(&uc_main, &uc_f);
    f(3);
}

void f(int arg1)
{
    int i;
    printf("f(%d) stack %p\n", arg1, &i);
}

产出

f(1) stack 0x7ffc5dff9274
f(2) stack 0x564b1538a3f4
f(3) stack 0x7ffc5dff9274

参见makecontext, swapcontext (SUSv2, POSIX.1-2001)

相关问题