66

我最近开始学习 CPU 和操作系统的工作原理,对带有提供多任务处理的操作系统的单 CPU 机器的操作感到有些困惑。

假设我的机器只有一个 CPU,这意味着在任何给定时间,只能运行一个进程。

现在,我只能假设操作系统用来控制对宝贵CPU时间的访问的调度器也是一个进程。

因此,在这台机器中,用户进程或调度系统进程在任何给定时间点都在运行,但不能同时运行。

所以这里有一个问题:

一旦调度器将 CPU 的控制权交给另一个进程,它如何重新获得 CPU 时间来再次运行自己来完成它的调度工作?我的意思是,如果当前运行的任何给定进程都没有产生 CPU,调度程序本身如何再次运行并确保正确的多任务处理?

到目前为止,我一直在想,如果用户进程通过系统调用请求 I/O 操作,那么在系统调用中我们可以确保调度程序再次分配一些 CPU 时间。但我什至不确定这是否以这种方式工作。

另一方面,如果有问题的用户进程本质上是受 CPU 限制的,那么从这个角度来看,它可以永远运行,永远不会让其他进程,甚至调度程序再次运行。

假设时间片调度,我不知道调度程序如何在另一个进程甚至没有运行的情况下分割时间来执行另一个进程?

我非常感谢您在这方面提供的任何见解或参考。

4

3 回答 3

53

操作系统设置了一个硬件定时器(可编程间隔定时器或 PIT),它每 N 毫秒产生一个中断。该中断被传递到内核并且用户代码被中断。

它像任何其他硬件中断一样工作。例如,您的磁盘将在完成 IO 后强制切换到内核。

于 2012-07-13T15:42:45.593 回答
12

谷歌“中断”。中断是多线程、抢占式内核(如 Linux/Windows)的核心。没有中断,操作系统永远不会做任何事情。

在调查/学习时,尽量忽略任何在第一段中提到“定时器中断”、“循环”和“时间片”或“量子”的解释——即使不是真的错误,它们也是危险的误导。

就操作系统而言,中断有两种形式:

  • 硬件中断——由来自外围设备的实际硬件信号启动的中断。这些可能在(几乎)任何时间发生,并将执行从可能正在运行的任何线程切换到驱动程序中的代码。

  • 软件中断——由当前运行线程的操作系统调用启动的中断。

任何一个中断都可以请求调度程序使正在等待/运行的线程准备好/运行,或者导致正在等待/运行的线程被抢占。

最重要的中断是来自外围驱动程序的那些硬件中断——那些使线程准备好等待来自磁盘、NIC 卡、鼠标、键盘、USB 等的 IO 的中断。使用抢占式内核的最重要原因,以及所有锁定问题,同步、信令等,是因为此类系统具有非常好的 IO 性能,因为硬件外围设备可以快速使等待来自该硬件的数据的线程准备好/运行,而不会因线程不屈服或等待周期性而导致任何延迟计时器重新安排。

导致周期性调度运行的硬件定时器中断很重要,因为许多系统调用都有超时,以防万一,例如,来自外围设备的响应花费的时间比应有的时间长。

在多核系统上,操作系统有一个处理器间驱动程序,可以导致其他内核上的硬件中断,从而允许操作系统将线程中断/调度/分派到多个内核上。

在严重过载的机器上,或那些运行 CPU 密集型应用程序(少数)的机器上,操作系统可以使用周期性计时器中断和由此产生的调度,循环通过一组大于可用内核数量的就绪线程,并允许每个人共享可用的 CPU 资源。在大多数系统上,这种情况很少发生,而且并不重要。

每次我看到“量子”、“放弃他们剩余的时间片”、“循环”等类似内容时,我都会畏缩......

于 2012-07-14T09:56:20.917 回答
4

为了补充@usr的答案,引用Understanding the Linux Kernel

schedule() 函数

schedule() 实现调度器。它的目标是在运行队列列表中找到一个进程,然后将 CPU 分配给它。它由几个内核例程直接或以惰性方式调用。[...]

延迟调用

调度程序也可以通过将当前 [process] 的 need_resched 字段设置为 1 以惰性方式调用。因为在恢复执行用户模式进程之前总是检查该字段的值(请参阅“返回”部分从第 4 章中的“中断和异常”开始),schedule() 肯定会在不久的将来被调用。

于 2012-07-13T15:47:59.327 回答