在内存中创建和使用新堆栈

标签 c linux stack

由于某些特殊原因(请不要问我为什么),对于某些功能,我想使用单独的堆栈。因此,例如,假设我希望函数 malloc 使用不同的堆栈进行处理,我需要在调用它之前切换到新创建的堆栈并返回到程序使用的原始堆栈完成后。所以算法应该是这样的。

switch_to_new_stack
call malloc
swith back to the original stack

执行此操作最简单、最有效的方法是什么?有什么想法吗?

最佳答案

它可能不符合您对简单或高效的定义,但以下可能是一种方法:

#include <stdio.h>
#include <stdlib.h>

#include <ucontext.h>

/* utility functions */
static void getctx(ucontext_t* ucp)
{
    if (getcontext(ucp) == -1) {
        perror("getcontext");
        exit(EXIT_FAILURE);
    }
}

static void print_sp()
{
#if defined(__x86_64)
    unsigned long long x; asm ("mov %%rsp, %0" : "=m" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__i386)
    unsigned long x; asm ("mov %%esp, %0" : "=m" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__) && defined(__PPC64__)
    unsigned long long x; asm ("addi %0, 1, 0" : "=r" (x));
    printf("sp: %p\n",(void*)x);
#elif defined(__powerpc__)
    unsigned long x; asm ("addi %0, 1, 0" : "=r" (x));
    printf("sp: %p\n",(void*)x);
#else
    printf("unknown architecture\n");
#endif
}


/* stack for 'my_alloc', size arbitrarily chosen */
static int malloc_stack[1024];
static ucontext_t malloc_context; /* context malloc will run in */
static ucontext_t current_context; /* context to return to */

static void my_malloc(size_t sz)
{
    printf("in my_malloc(%zu) ", sz);
    print_sp();
}

void call_my_malloc(size_t sz)
{
    /* prepare context for malloc */
    getctx(&malloc_context);
    malloc_context.uc_stack.ss_sp = malloc_stack;
    malloc_context.uc_stack.ss_size = sizeof(malloc_stack);
    malloc_context.uc_link = &current_context;
    makecontext(&malloc_context, (void(*)())my_malloc, 1, sz);

    if (swapcontext(&current_context, &malloc_context) == -1) {
        perror("swapcontext");
        exit(EXIT_FAILURE);
    }
}

int main()
{
    printf("malloc_stack = %p\n", (void*)malloc_stack);
    printf("in main ");
    print_sp();
    call_my_malloc(42);
    printf("in main ");
    print_sp();
    return 0;
}

这应该适用于支持 makecontext(3) 的所有平台。引用联机帮助页(我也从中获得了示例代码的灵感):

The interpretation of ucp->uc_stack is just as in sigaltstack(2), namely, this struct contains the start and length of a memory area to be used as the stack, regardless of the direction of growth of the stack. Thus, it is not necessary for the user program to worry about this direction.

PPC64 的示例输出:

$ gcc -o stack stack.c -Wall -Wextra -W -ggdb -std=gnu99 -pedantic -Werror -m64 && ./stack
malloc_stack = 0x10010fe0
in main sp: 0xfffffe44420
in my_malloc(42) sp: 0x10011e20
in main sp: 0xfffffe44420

关于在内存中创建和使用新堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7260612/

相关文章:

linux - python程序矩阵转置

c - 程序执行未按预期顺序发生

c - 函数参数中的逗号运算符

c - makefile 在 Windows 上适用于 cygwin,但不适用于 ubuntu

python - 如何在 Linux Ubuntu 10.04 上为 Python 安装 lpsolve 模块?

linux - 具有不同内核的 D​​ocker

java - 在 Java 中使用树计算 Postfix 表达式

c - Stack ADT实现中难以理解的表达

c++ - 我怎样才能避免把这个变量放在堆栈上?

c - 使用 realloc 与 free -> malloc 函数的区别