17

只是好奇。Sleep() 函数实际上是如何工作的(在 windows.h 中声明)?也许不仅仅是那个实现,而是任何人。我的意思是-它是如何实施的?它如何使代码在特定时间“停止”?还对 cin >> 和那些实际工作的方式感到好奇。他们具体做什么?

我知道如何“阻止”某些东西继续运行的唯一方法是使用 while 循环,但考虑到与调用从 stdin 读取方法时发生的情况相比,这需要大量的处理能力(只是比较一段时间(真实)从标准输入读取),我猜这不是他们所做的。

4

7 回答 7

29

操作系统使用一种称为调度程序的机制来保持其管理的所有线程或进程良好地协同工作。

每秒几次,计算机的硬件时钟会中断 CPU,从而导致操作系统的调度程序被激活。然后调度程序将查看所有尝试运行的进程并决定下一个时间片运行哪个进程。

它用来决定的不同事物取决于每个进程的状态,以及它之前有多少时间。所以如果当前进程一直在大量使用CPU,阻止其他进程继续进行,它会让当前进程等待并换入另一个进程,以便它可以做一些工作。

但是,更常见的情况是,大多数进程将处于等待状态。例如,如果一个进程正在等待来自控制台的输入,操作系统可以查看进程信息并查看它等待的 io 端口。它可以检查这些端口以查看它们是否有任何数据可供进程处理。如果他们这样做了,它可以再次启动该过程,但如果没有数据,那么该过程将被跳过当前时间片。

至于sleep(),任何进程都可以通知操作系统它想等待一段时间。然后调度程序将在硬件中断之前被激活(这也是当进程尝试从没有数据可供读取的流中进行阻塞读取时发生的情况),并且操作系统会记下该进程是什么等待。对于睡眠,该进程正在等待警报响起,或者它可能会在每次重新启动时再次屈服,直到计时器结束。

由于操作系统仅在某些事情导致它抢占正在运行的进程后才恢复进程,例如我提到的进程让步或硬件定时器中断,sleep()所以不是很准确,准确度取决于操作系统或硬件,但通常在一毫秒或多毫秒。

如果需要更高的准确性,或者等待时间很短,唯一的选择是使用您提到的繁忙循环结构。

于 2009-07-03T21:08:32.150 回答
3

操作系统调度进程如何运行(哪些进程有资格运行,以什么顺序......)。 Sleep()可能会发出一个系统调用,告诉内核“不要让我使用处理器x毫秒”。

于 2009-07-03T21:05:46.710 回答
2

简而言之,Sleep() 告诉操作系统暂时忽略进程/线程。

于 2009-07-03T21:15:37.753 回答
1

'cin' 使用了大量的重载运算符。'>>',通常是右位移,对于 C++ 中几乎所有类型的右手操作数都被重载。每个都提供了一个单独的函数,该函数从控制台读取并将输入转换为您给定的任何变量类型。例如:

std::cin::operator>> (int &rhs);

那不是真正的 C++——我已经有一段时间没有使用流和重载了,所以我不记得返回类型或参数的确切顺序。然而,当您运行 cin >> 一个整数变量时,会调用此函数。

确切的底层实现取决于操作系统。

于 2009-07-03T23:36:16.470 回答
0

答案取决于操作系统,但一般来说,操作系统要么安排一些其他代码在另一个线程的其他地方运行,要么如果它确实无关,它会让 CPU 等待硬件事件发生,这会导致CPU 跳转到一些称为中断处理程序的代码,然后它可以决定运行哪些代码。

于 2009-07-03T21:07:25.803 回答
0

如果您正在寻找一种在多线程程序中阻塞线程/进程的更可控方式,请查看信号量、互斥量、关键部分和事件。这些都是用于阻塞进程或线程的技术(无需通过 while 构造加载 CPU)。

它们基本上使用等待/信号习语,其中被阻塞的线程正在等待,另一个进程发出信号告诉它重新开始。这些(至少在 Windows 中)也可以有超时,因此提供了与 Sleep() 类似的功能。

于 2009-07-03T21:16:25.690 回答
0

在底层,系统有一个称为“调度程序”的例程,它将所有正在运行的程序的指令分派给实际运行它们的 CPU。像“Sleep”和“usleep”这样的系统调用与告诉调度程序在固定时间内忽略该线程或进程的指令相匹配。

至于 C++ 流,“cin”隐藏了您正在访问的实际文件句柄(stdin 和 stdout 实际上就是这样的句柄),并且它的“>>”运算符隐藏了读取和写入的底层调用。由于它是一个接口,因此实现可以是特定于操作系统的,但从概念上讲,它仍然在做诸如 printf 和 scanf 之类的事情。

于 2012-05-17T16:08:01.937 回答