【问题标题】:Gracefully (i.e eventually cooperatively) suspend thread execution优雅地(即最终合作地)挂起线程执行
【发布时间】:2011-02-10 13:41:40
【问题描述】:

我必须开发一个尝试模拟嵌入式目标的执行流程的应用程序。该目标有 2 个优先级:最高优先级优先于最低优先级。低优先级由轮询调度程序管理,轮流调度程序为每个线程提供 1ms 的执行时间。

我的目标是编写一个库,提供 thread_create、thread_start 和我的目标上可用的所有系统调用,并使用 POSIX 函数在标准 PC 上本地重现行为。
因此,当一个高优先级线程执行时,低优先级线程应该被挂起,无论它们当时正在做什么。低优先级线程的实现有责任确保它不会受到干扰。

我现在挂起一个线程通常是不安全的,这就解释了为什么我没有找到任何“suspend(pid)”函数。

我基本上想出了两个解决问题的方法:
-找到一种方法在高优先级线程启动时挂起低优先级线程(并在没有更多高优先级活动时恢复它们)
- 在我的低优先级代码中的任何地方定期调用一个非常小的“suspend_if_necessary”函数,并且每当必须启动高优先级时,等待所有低优先级进程调用该函数并被挂起,作为单个高优先级线程执行,然后恢复他们都。

即使它不是那么干净,我也很喜欢第二种解决方案,但仍然有一个问题:如何在不更改所有代码的情况下到处调用函数? 我想知道是否有一种简单的方法可以做到这一点,有点像调试代码:在执行的每一行添加一个钩子调用来检查一个标志并在该标志发生变化时运行一些特定的代码?

如果该问题有一个简单的解决方案,我会非常高兴,因为我确实需要代表目标执行流程的行为......

提前致谢,

咕噜。

【问题讨论】:

  • 顺便说一句,高优先级线程只能由 3 个来源启动:低优先级线程启动、外部中断启动或睡眠后启动。所有这些来源都位于我的库中,因此我“知道”它并且可以立即向其他线程发送任何消息。

标签: c multithreading thread-safety pthreads


【解决方案1】:

不幸的是,用真正的线程实现你想要的实际上是不可能的——即使重新启动高优先级线程,也可能需要任意长的时间才能重新安排高优先级线程并挂起所有低优先级线程.此外,仅使用 POSIX 线程没有可靠的方法来确定高优先级线程是否被阻塞;您可以尝试手动跟踪事物,但这会带来误报(线程被某些东西阻塞,但低优先级线程认为它正在运行并自行挂起)和误报(您错过了恢复的注释,或者两者之间存在滞后)的风险线程实际上已恢复并且何时将自己标记为正在运行)。

如果您想使用纯 POSIX 实现线程优先级系统,一种选择是使用线程,而是使用setcontext 进行协作多任务处理。这将允许您在用户级别的线程之间进行交换。但是,在这种情况下,您必须显式让出 CPU。它也无助于阻塞系统调用,这会阻塞应用程序中的所有线程;但由于您正在编写模拟器,这可能不是问题。

也许还可以在信号处理程序中使用 setcontext 交换线程;我自己没有测试过这种情况,但值得尝试在 SIGALRM 处理程序中使用 setcontext 进行调度。

【讨论】:

  • 关于您的第一点:在我的想法中,高优先级线程将等待锁定(信号量),直到所有其他活动线程(我可以数出它们)实际上都被挂起。唯一缺少的是让所有其他线程调用这个“suspend_if_necessary”函数。另一方面,高优先级和低优先级线程只能在我的库中的某些东西(事件,管道读取......)上被阻塞,所以这就是我认为是内部控制的(我现在哪个线程处于活动状态,挂起...... .)
【解决方案2】:

要挂起一个线程,你要把它休眠。如果您希望能够根据命令唤醒它,请使用sigwait 将其休眠,这会使线程进入休眠状态,直到它收到信号。您可以使用pthread_kill 向特定线程发送信号(这个名字很疯狂,但实际上它只是向线程发送信号)。这是一种非常快速的睡眠和唤醒线程的方法。比条件变量快 40 倍,而且非常简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2011-02-14
    • 2015-06-07
    • 2012-03-16
    • 1970-01-01
    相关资源
    最近更新 更多