Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在内存中创建和使用新堆栈_C_Linux_Stack - Fatal编程技术网

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

C 在内存中创建和使用新堆栈,c,linux,stack,C,Linux,Stack,出于某些特殊原因(请不要问我为什么),对于某些函数,我希望使用单独的堆栈。例如,假设我希望函数malloc使用不同的堆栈进行处理,我需要在调用之前切换到新创建的堆栈,并在调用完成后返回程序使用的原始堆栈。所以算法应该是这样的 switch_to_new_stack call malloc swith back to the original stack 最简单、最有效的方法是什么?有什么想法吗?这可能不符合您对简单或高效的定义,但以下可能是一种方法: #include <stdio.h&

出于某些特殊原因(请不要问我为什么),对于某些函数,我希望使用单独的堆栈。例如,假设我希望函数
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;
}

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

#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;
}

GCC支持拆分堆栈,其工作原理有点像您所描述的

项目的目标是不同的,但实现将满足您的要求

拆分堆栈的目标是允许不连续的堆栈根据需要自动增长。这意味着您可以运行多个线程,每个线程从一个小堆栈开始,并根据程序的要求使堆栈增长和收缩。因此,在编写多线程程序时,不再需要考虑堆栈要求。典型多线程程序的内存使用会显著减少,因为每个线程不需要最坏情况下的堆栈大小。可以在32位地址空间中运行数百万个线程(完整的NPTL线程或协同例程)


GCC支持拆分堆栈,其工作原理有点像您所描述的

项目的目标是不同的,但实现将满足您的要求

拆分堆栈的目标是允许不连续的堆栈根据需要自动增长。这意味着您可以运行多个线程,每个线程从一个小堆栈开始,并根据程序的要求使堆栈增长和收缩。因此,在编写多线程程序时,不再需要考虑堆栈要求。典型多线程程序的内存使用会显著减少,因为每个线程不需要最坏情况下的堆栈大小。可以在32位地址空间中运行数百万个线程(完整的NPTL线程或协同例程)


为什么要使用替代堆栈?(对不起)你看过
man3makecontext
了吗?线程使用自己的堆栈运行;您可以创建一个线程来运行malloc;调用者只会等待线程完成。这是一个简单的问题,切换到一个新的堆栈是一个很好理解的操作,唯一的疑问是在linux的用户模式下是否可能(问题的要点)以及提问者为什么要这样做(评论的要点,但与答案无关:要么有一种方法可以在不同的体系结构上跨linux移植,要么没有,不管提问者是否最好改做其他事情,这都是正确的)。此外,我还要为更多的问题投票。任何解决方案都是特定于系统的。C语言标准甚至不使用“堆栈”一词,而且现实世界中的C实现也不使用连续堆栈来分配具有自动存储持续时间的对象(想想堆分配的激活记录链表)。我相信您知道,
malloc
分配的空间不在堆栈上;
malloc
使用的任何堆栈空间都将是调用本身的本地空间,并将在
malloc
返回后立即释放。我只能相信您的话,您需要这样做,但我想不出一个好的理由。您为什么要这样做要使用替代堆栈?(抱歉)你看过
man 3 makecontext
?线程使用自己的堆栈运行;你可以创建一个线程来运行malloc;调用者只需等待线程完成就可以了。+1.这是一个简单的问题,切换到新堆栈是一个很好理解的操作,唯一的疑问是在linu的用户模式下是否可能x(问题的要点)以及提问者为什么要这么做(评论的要点,但与答案无关:要么有一种方法可以在不同的体系结构上跨linux移植,要么没有,不管是否建议提问者做其他事情都可以)。此外,我还要为更多的问题投票。任何解决方案都是特定于系统的。C语言标准甚至不使用“堆栈”一词,而且现实世界中的C实现也不使用连续堆栈来分配具有自动存储持续时间的对象(想想堆分配的激活记录链表)。我相信您知道,
malloc
分配的空间不在堆栈上;
malloc
使用的任何堆栈空间都将是调用本身的本地空间,并将在
malloc
返回时立即释放。我只能相信您的话,您需要这样做,但我想不出一个好的理由。谢谢。我会的看看。希望会有帮助!谢谢。我会看的。希望会有帮助!