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 = ¤t_context;
makecontext(&malloc_context, (void(*)())my_malloc, 1, sz);
if (swapcontext(¤t_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 = ¤t_context;
makecontext(&malloc_context, (void(*)())my_malloc, 1, sz);
if (swapcontext(¤t_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
返回时立即释放。我只能相信您的话,您需要这样做,但我想不出一个好的理由。谢谢。我会的看看。希望会有帮助!谢谢。我会看的。希望会有帮助!