上下文切换 - makecontext 和 swapcontext 在这里工作吗 (OSX)
Context switching - Is makecontext and swapcontext working here (OSX)
我对上下文切换很感兴趣。我已将示例代码复制到一个文件中
http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html
我为 OSX 定义了宏 _XOPEN_SOURCE。
#define _XOPEN_SOURCE
#include <stdio.h>
#include <ucontext.h>
static ucontext_t ctx[3];
static void
f1 (void)
{
puts("start f1");
swapcontext(&ctx[1], &ctx[2]);
puts("finish f1");
}
static void
f2 (void)
{
puts("start f2");
swapcontext(&ctx[2], &ctx[1]);
puts("finish f2");
}
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);
ctx[2].uc_stack.ss_sp = st2;
ctx[2].uc_stack.ss_size = sizeof st2;
ctx[2].uc_link = &ctx[1];
makecontext(&ctx[2], f2, 0);
swapcontext(&ctx[0], &ctx[2]);
return 0;
}
我建
gcc -o 上下文 context.c -g
关于 get、make、swap context 被弃用的问题向我吐槽。嗯
当我 运行 它只是挂起。它似乎没有崩溃。它只是挂起。
我尝试使用 gdb,但是一旦进入交换上下文,它就是空白的。它不会跳入 f1。我一直按回车键,它只会将光标移动到控制台上的新行中?
知道发生了什么事吗?与研究 Mac/deprecate 方法有关?
谢谢
看起来您的代码只是 the ucontext documentation 中的 copy/pasted,这肯定让人沮丧,因为它无法正常工作...
据我所知,您的筹码太少了。我无法让它与任何小于 32KiB 的堆栈一起工作。
尝试进行这些更改:
#define STACK_SIZE (1<<15) // 32KiB
// . . .
char st1[STACK_SIZE];
char st2[STACK_SIZE];
yup fixed it. why did it fix it though?
好吧,让我们更深入地研究一下这个问题。首先,让我们看看到底发生了什么。
When I run it it just hangs. It doesn't seem to crash. It just hangs.
如果你使用一些调试器(一定要使用 lldb——gdb 在 os x 上不能正常工作),那么你会发现当应用程序是 "hanging",它实际上在你的 main
函数中以一个奇怪的循环旋转,如下面评论中的箭头所示。
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);// <---------------------+ back to here
ctx[2].uc_stack.ss_sp = st2;// |
ctx[2].uc_stack.ss_size = sizeof st2;// |
ctx[2].uc_link = &ctx[1];// |
makecontext(&ctx[2], f2, 0); // |
// |
puts("about to swap...");// |
// |
swapcontext(&ctx[0], &ctx[2]);// ------------+ jumps from here
return 0;
}
请注意,我在上面的循环中间添加了一个额外的 puts
调用。如果您再次添加该行和 compile/run,那么您将看到它开始喷出字符串 "about to swap..."
ad infinitum.[=,而不是程序只是挂起。 36=]
显然,根据给定的堆栈大小,有些事情正在发生,所以让我们只查找引用 ss_size
的所有地方...
(注意:Apple ucontext 实现的权威源代码位于 https://opensource.apple.com/source/, but there's a GitHub mirror,我将使用它,因为它更适合搜索和链接。)
如果我们take a look at makecontext.c
,我们会看到这样的东西:
if (ucp->uc_stack.ss_size < MINSIGSTKSZ) {
// fail without an error code since makecontext is a void function
return;
}
嗯,太好了!什么是 MINSIGSTKSZ
?好吧,让我们 a look in signal.h
:
#define MINSIGSTKSZ 32768 /* (32K)minimum allowable stack */
#define SIGSTKSZ 131072 /* (128K)recommended stack size */
显然这些值实际上是 part of the POSIX standard. Although I don't see anything in the ucontext documentation that references these values, I guess it's kind of implied since 。
无论如何,这解释了我们所看到的古怪行为。由于 makecontext
调用因堆栈太小而失败,对 getcontext(&ctx[2])
的调用是设置 ctx[2]
的内容,因此对 swapcontext(&ctx[0], &ctx[2])
的调用只是最终再次换回那条线,创建无限循环...
有趣的是,MINSIGSTKSZ
在 os x 上是 32768 字节,但在我的 linux 盒子上只有 2048 字节,这解释了为什么它在 linux 上有效但在 os x.
基于所有这些,看起来更安全的选择是使用 sys/signal.h
:
中推荐的堆栈大小
char st1[SIGSTKSZ];
char st2[SIGSTKSZ];
那个,或者切换到未弃用的东西。如果您不反对 C++,您可以看看 Boost.Context。
我对上下文切换很感兴趣。我已将示例代码复制到一个文件中 http://pubs.opengroup.org/onlinepubs/009695399/functions/makecontext.html
我为 OSX 定义了宏 _XOPEN_SOURCE。
#define _XOPEN_SOURCE
#include <stdio.h>
#include <ucontext.h>
static ucontext_t ctx[3];
static void
f1 (void)
{
puts("start f1");
swapcontext(&ctx[1], &ctx[2]);
puts("finish f1");
}
static void
f2 (void)
{
puts("start f2");
swapcontext(&ctx[2], &ctx[1]);
puts("finish f2");
}
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);
ctx[2].uc_stack.ss_sp = st2;
ctx[2].uc_stack.ss_size = sizeof st2;
ctx[2].uc_link = &ctx[1];
makecontext(&ctx[2], f2, 0);
swapcontext(&ctx[0], &ctx[2]);
return 0;
}
我建
gcc -o 上下文 context.c -g
关于 get、make、swap context 被弃用的问题向我吐槽。嗯
当我 运行 它只是挂起。它似乎没有崩溃。它只是挂起。
我尝试使用 gdb,但是一旦进入交换上下文,它就是空白的。它不会跳入 f1。我一直按回车键,它只会将光标移动到控制台上的新行中?
知道发生了什么事吗?与研究 Mac/deprecate 方法有关?
谢谢
看起来您的代码只是 the ucontext documentation 中的 copy/pasted,这肯定让人沮丧,因为它无法正常工作...
据我所知,您的筹码太少了。我无法让它与任何小于 32KiB 的堆栈一起工作。
尝试进行这些更改:
#define STACK_SIZE (1<<15) // 32KiB
// . . .
char st1[STACK_SIZE];
char st2[STACK_SIZE];
yup fixed it. why did it fix it though?
好吧,让我们更深入地研究一下这个问题。首先,让我们看看到底发生了什么。
When I run it it just hangs. It doesn't seem to crash. It just hangs.
如果你使用一些调试器(一定要使用 lldb——gdb 在 os x 上不能正常工作),那么你会发现当应用程序是 "hanging",它实际上在你的 main
函数中以一个奇怪的循环旋转,如下面评论中的箭头所示。
int
main (void)
{
char st1[8192];
char st2[8192];
getcontext(&ctx[1]);
ctx[1].uc_stack.ss_sp = st1;
ctx[1].uc_stack.ss_size = sizeof st1;
ctx[1].uc_link = &ctx[0];
makecontext(&ctx[1], f1, 0);
getcontext(&ctx[2]);// <---------------------+ back to here
ctx[2].uc_stack.ss_sp = st2;// |
ctx[2].uc_stack.ss_size = sizeof st2;// |
ctx[2].uc_link = &ctx[1];// |
makecontext(&ctx[2], f2, 0); // |
// |
puts("about to swap...");// |
// |
swapcontext(&ctx[0], &ctx[2]);// ------------+ jumps from here
return 0;
}
请注意,我在上面的循环中间添加了一个额外的 puts
调用。如果您再次添加该行和 compile/run,那么您将看到它开始喷出字符串 "about to swap..."
ad infinitum.[=,而不是程序只是挂起。 36=]
显然,根据给定的堆栈大小,有些事情正在发生,所以让我们只查找引用 ss_size
的所有地方...
(注意:Apple ucontext 实现的权威源代码位于 https://opensource.apple.com/source/, but there's a GitHub mirror,我将使用它,因为它更适合搜索和链接。)
如果我们take a look at makecontext.c
,我们会看到这样的东西:
if (ucp->uc_stack.ss_size < MINSIGSTKSZ) {
// fail without an error code since makecontext is a void function
return;
}
嗯,太好了!什么是 MINSIGSTKSZ
?好吧,让我们 a look in signal.h
:
#define MINSIGSTKSZ 32768 /* (32K)minimum allowable stack */
#define SIGSTKSZ 131072 /* (128K)recommended stack size */
显然这些值实际上是 part of the POSIX standard. Although I don't see anything in the ucontext documentation that references these values, I guess it's kind of implied since
无论如何,这解释了我们所看到的古怪行为。由于 makecontext
调用因堆栈太小而失败,对 getcontext(&ctx[2])
的调用是设置 ctx[2]
的内容,因此对 swapcontext(&ctx[0], &ctx[2])
的调用只是最终再次换回那条线,创建无限循环...
有趣的是,MINSIGSTKSZ
在 os x 上是 32768 字节,但在我的 linux 盒子上只有 2048 字节,这解释了为什么它在 linux 上有效但在 os x.
基于所有这些,看起来更安全的选择是使用 sys/signal.h
:
char st1[SIGSTKSZ];
char st2[SIGSTKSZ];
那个,或者切换到未弃用的东西。如果您不反对 C++,您可以看看 Boost.Context。