【问题标题】:Is there something to replace the <ucontext.h> functions?有什么东西可以代替 <ucontext.h> 功能吗?
【发布时间】:2010-11-28 20:44:57
【问题描述】:

&lt;ucontext.h&gt; 中的用户线程函数已弃用,因为它们使用了已弃用的 C 功能(use a function declaration with empty parentheses for an argument)。

他们有标准的替代品吗?我不觉得成熟的线程擅长实现协作线程。

【问题讨论】:

  • 您不了解此处实际弃用的内容。 makecontext 声明绝对没问题并且不被弃用——第二个参数实际上是一个没有参数的函数。 /is/ 不推荐使用的是声明一个函数,该函数将使用() 接受参数,然后将参数放入定义中。您已经接受了一个没有指出这一点的答案(十年前,哈哈),但是关于 ucontext.h 没有什么是过时的。
  • @BadZen, 已从 Open Group Base Specification in revision 7 (2018) 中删除(您可以在第 6 版中找到 ucontext.h,但在第 7 版中没有)。 Glibc 仍然有它,但它是来自达尔文的 gone with prejudice

标签: c posix user-thread


【解决方案1】:

如果你真的想做ucontext.h 函数允许的事情,我会继续使用它们。其他任何东西都将不那么便携。在 POSIX 中将它们标记为过时似乎是委员会成员犯的一个可怕的迂腐错误。 POSIX 本身要求函数指针和数据指针大小相同,并且函数指针可以表示为void *,而 C 本身需要在函数指针类型之间进行类型转换并返回到往返安全,所以有很多方法这个问题本来可以解决的。

有一个真正的问题,除非可变参数和非可变参数函数的调用约定碰巧是一样的(即使那样,它是否可以稳健地完成也是相当值得怀疑的)。然而,这个问题可以简单地通过弃用 makecontext 以外的任何形式使用 makecontext(ucp, func, 1, (void *)arg); 来解决。

也许更好的问题是为什么您认为ucontext.h 函数是处理线程的最佳方式。如果您确实想使用它们,我可能会建议编写一个包装器接口,您可以使用ucontext.h 实现 either 与 pthreads,然后比较性能和膨胀。这还有一个好处,如果未来的系统放弃对ucontext.h 的支持,您可以简单地切换到使用基于 pthread 的实现进行编译,一切都会正常工作。 (到那时,膨胀可能不那么重要,多核/SMP 的好处可能会很大,希望 pthread 实现不会那么膨胀。)

编辑(根据 OP 的要求):要使用 pthread 实现“协作线程”,您需要条件变量。这是一个不错的 pthreads 教程,其中包含有关使用它们的信息:

https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

您的“将执行移交给线程 X”的协作式多任务处理原语将类似于:

self->flag = 0;
other_thread->flag = 1;
pthread_mutex_lock(other_thread->mutex);
pthread_cond_signal(other_thread->cond);
pthread_mutex_unlock(other_thread->mutex);
pthread_mutex_lock(self->mutex);
while (!self->flag)
    pthread_cond_wait(self->cond, self->mutex);
pthread_mutex_unlock(self->mutex);

希望我没问题;至少总体思路是正确的。如果有人看到错误,请发表评论,以便我修复它。这种用法可能完全不需要一半的锁定(other_thread 的互斥锁),因此您可以将互斥锁设为task_switch 函数中的局部变量。您真正要做的就是使用pthread_cond_waitpthread_cond_signal 作为“进入睡眠”和“唤醒其他线程”原语。

【讨论】:

  • 我正在寻找协作线程,这是 pthread 不做的。在协作线程/用户线程中,每个线程负责让其他线程运行。 pthreads 由操作系统调度,这使得实现协作线程很痛苦。
  • 也许您正在寻找条件变量? computing.llnl.gov/tutorials/pthreads/#ConditionVariables
  • 添加了一些关于如何使用 pthread 进行此操作的详细信息。
  • 我知道这是可能的(尽管感谢您的参考),但它比 getcontext/setcontext 提供的方便得多。
  • 如果你制作了一个漂亮的包装器和不透明的数据结构来表示你的线程,那么界面应该看起来与ucontext 几乎相同(除了 POSIX 人讨厌的丑陋原型)。
【解决方案2】:

对于它的价值,有一个 Boost.Context 库,它是 recently accepted,只需要合并到官方 Boost 版本中。 Boost.Context 解决了与 POSIX ucontext 系列相同的用例:低开销的协作上下文切换。作者一直在努力解决性能问题。

【讨论】:

  • 这很有趣。我不再需要它了,但如果我再次需要类似的东西,我会知道去哪里找。
【解决方案3】:

不,它们没有标准替代品。

你的选择是

  • 继续使用&lt;ucontext.h&gt;,即使它们包含过时的C。
  • 切换到 pthreads
  • 编写自己的协线程库
  • 使用现有的(并且可能不太便携的)共线程库,例如 http://swtch.com/libtask/,尽管许多此类库是在 ucontext.h 之上实现的

【讨论】:

  • 我想知道这些不那么便携的库是否可以移植到使用 pthreads 而不是操作系统/机器特定的黑客,类似于我回答中的方法......
  • 可能,但重量级要大得多。
  • 我不会说“很多”。上下文切换要多几千个周期(或者使用 SMP/多核可能更少),每个线程多出几十 kb(我猜内核空间中的 2-4 页和用户空间中的相同数量)。跨度>
  • 我确实会说很多;关心使用协程的人肯定关心性能,仅仅因为漂亮的设计而强制上下文切换对他们的情况没有帮助
【解决方案4】:

开放组基本规范第 6 期 IEEE Std 1003.1, 2004 版

仍然列出具有相同已弃用语法的 makecontext() 和 swapcontext()。我没有看到任何更新的东西。

【讨论】:

    猜你喜欢
    • 2012-10-18
    • 1970-01-01
    • 2011-02-25
    • 2021-03-08
    • 1970-01-01
    • 2017-04-08
    • 2017-10-23
    • 2011-07-12
    • 1970-01-01
    相关资源
    最近更新 更多