sched_yield() 系统调用和实时调度策略

问题描述

我想知道如何在多线程的Linux内核中使用调度机制,我看到sched_yield()系统调用可以将当前线程发送到进程队列的末尾。由于 SCHED_OTHER认调度策略,因此手册不建议在使用 SCHED_OTHER 时使用此系统调用,因为它旨在与实时调度策略 (man 2 sched_yield) 和未指定 SCHED_OTHER:

sched_yield() 旨在用于实时调度策略(即 SCHED_FIFO 或 SCHED_RR)。未指定将 sched_yield() 与非确定性调度策略(例如 SCHED_OTHER)一起使用,这很可能意味着您的应用设计已损坏。

但是,我从 RedHat 文档中看到 this pagesched_yield() 不应该用于实时任务:

sched_yield 系统调用一个线程使用,允许其他线程有机会运行。通常当使用 sched_yield 时,线程可以走到运行队列的末尾,需要很长时间才能再次调度,或者可以立即重新调度,从而在 cpu 上创建一个繁忙的循环。调度程序能够更好地确定何时以及是否确实有其他线程想要运行。避免在任何 RT 任务中使用 sched_yield。

那么我应该如何使用 sched_yield() 系统调用?这对 SCHED_OTHERSCHED_FIFO 政策有何作用?据我了解,使用 SCHED_FIFO 策略时,除非出现 sched_yield(),否则线程不会被中断,然后除非结束,否则将处理第二个请求的线程,而第一个线程将在已处理所有线程队列(具有 FIFO 行为)。

此外,这个系统调用会对 SCHED_RR 策略做什么,因为所有线程在每个量程中都被部分处理?

解决方法

Linus Torvalds' comment about sched_yield

“产量”的问题几乎没有定义。它的定义实际上是关于具有优先级的实时调度器的实时行为的单个队列。

但那个“定义”几乎与实际使用无关。有各种各样随机的人在使用它,有的可能会用它来锁定,有的可能会用它来做其他事情。

...

sched_yield() 基本上是历史垃圾。 即使对于定义的用法来说,这通常都是错误的,因为很久以前“我们一次只运行一件事”的时代已经过去了。如果您的 RT 系统实际上有多个并发线程(而不是仅限于专用 CPU),那么即使在那里也不是那么明确。但至少在那里你仍然可以假装它是。