2009-07-03 63 views
16

只是好奇。 Sleep()函數實際上是如何工作的(在windows.h中聲明的)?也許不僅僅是實現,而是任何人。我的意思是 - 它是如何實現的?它如何使代碼在特定時間「停止」?也好奇cin >>和那些實際上工作。他們究竟做了什麼?C++ - Sleep()和cin如何工作?

我知道如何「阻止」某些東西繼續運行的唯一方法是使用while循環,但考慮到與您調用方法讀取時發生的情況相比,這需要大量的處理能力stdin(比較一段時間(真)到從標準輸入讀取),我猜這不是他們做的。

回答

27

操作系統使用稱爲調度程序的機制來保持它所管理的所有線程或進程很好地一起工作。

每秒幾次,計算機的硬件時鐘中斷CPU,導致操作系統的調度程序被激活。然後,調度程序將查看所有正在嘗試運行的進程,並決定哪個進程在下一個時間片運行。

它用來決定的不同事情取決於每個進程的狀態,以及它以前有多少時間。因此,如果當前進程大量使用CPU,阻止其他進程取得進展,它將使當前進程在另一進程中等待並交換,以便它可以執行一些工作。

儘管如此,大多數進程將處於等待狀態。例如,如果某個進程正在等待來自控制檯的輸入,則操作系統可以查看進程信息並查看其正在等待的端口。它可以檢查這些端口,看它們是否有任何數據供進程使用。如果他們這樣做,它可以再次啓動進程,但是如果沒有數據,那麼當前時間片跳過該進程。

至於sleep(),任何進程都可以通知OS想要等待一段時間。即使在硬件中斷之前,調度程序也會被激活(當進程試圖從沒有準備好讀取數據的流中進行阻塞讀取時,也會發生這種情況),並且OS記錄了過程是什麼等待。對於睡眠,該過程正在等待警報消失,或者每次重新啓動時它都會再次產生,直到定時器啓動。由於操作系統只是在某些事件導致它搶佔正在運行的進程(如我提到的進程產生或硬件計時器中斷)時才恢復進程,所以sleep()不是很準確,它的準確性取決於操作系統或硬件,但它是通常在一個或多個毫秒的量級上。

如果需要更高的準確度或很短的等待時間,唯一的選擇是使用您提到的繁忙循環結構。

+0

很好的答案。 +1 – WolfmanDragon 2009-07-03 21:10:57

3

操作系統安排進程的運行方式(哪些進程有資格按照什麼順序運行......)。 Sleep()可能會發出一個系統調用,它告訴內核「不要讓我使用處理器爲x毫秒」。

+0

只是好奇。你如何自己打這樣的電話?如果你因爲隱藏的實現而無法在windows上運行,那麼可能是一個linux例子? – quano 2009-07-04 10:54:00

+0

GNU/Linux符合Posix系統調用。 Posix系統調用被指定爲C函數,但通常它們只是底層系統調用的包裝。如果你看看/usr/include/asm/unistd_32.h,你會看到系統調用了nanosleep()。 sleep()很可能是通過調用這個系統調用來實現的。在Windows上也有系統調用,但它們沒有記錄,所以幾乎沒有理由找出它們的工作方式。 – 2009-07-04 12:37:09

0

答案取決於操作系統,但一般來說,操作系統要麼安排其他代碼在另一個線程中的其他地方運行,要麼它實際上無所事事,它讓CPU等待,直到發生硬件事件發生,這會導致CPU跳轉到一些稱爲中斷處理程序的代碼,然後可以決定運行哪些代碼。

2

簡而言之,Sleep()告訴操作系統在一段時間內忽略進程/線程。

+0

如果是多線程過程呢? – user457015 2013-12-15 19:31:02

0

如果您正在尋找更多控制方式來阻止多線程程序中的線程/進程,請查看信號量,互斥鎖,臨界區和事件。這些都是用來阻塞進程或線程的技術(不需要通過while構造加載CPU)。

它們本質上是等待/信號習慣用法,其中被阻塞的線程正在等待,另一個進程發信號通知它再次開始。這些(至少在Windows中)也可以有超時,因此提供了與Sleep()類似的功能。

1

'cin'使用了大量的重載操作符。 '>>'通常是正確的位移,在C++中幾乎每種類型的右手操作數都會超載。爲每一個函數都提供了一個單獨的函數,它從控制檯讀取並將輸入轉換爲您提供的任何變量類型。例如:

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

這不是真正的C++ - 我還沒有和流工作,並在一段時間超載,所以我不記得的返回類型或參數的確切順序。不過,當你運行cin >>整型變量時,這個函數會被調用。

確切的底層實現取決於操作系統。

0

在較低的級別上,系統有一個稱爲「調度程序」的例程,它將所有正在運行的程序的指令分派到實際運行它們的CPU。諸如「睡眠」和「休眠」之類的系統調用與指示IGNORE指示該線程或進程持續一段固定時間的指令相匹配。對於C++流,「cin」隱藏了你正在訪問的實際文件句柄(stdin和stdout實際上就是這樣的句柄),而它的「>>」操作符隱藏了底層的讀寫請求。由於它的接口實現可以是特定於操作系統的,但從概念上講它仍然在做printf和scanf之類的東西。