操作系統的時間函數是怎麼實現的?

所有的編程語言都會提供關於時間的庫函數,比如sleep、wait、time、clock等,它們在操作系統中是怎麼實現的?與實際時間相比會有偏差嗎


cpu裡面有可編程間隔定時器(PIT,Programmable interval timer),目前x86-64/arm/8051-based的絕大多數cpu/mcu都是內置PIT的,PIT以一個可調節的時間間隔觸發時鐘中斷,使得操作系統的時鐘中斷處理程序可以可調節地周期性運行。時鐘中斷處理程序負責維護所有的軟體定時器,在當前進程的時間片用光,或有定時器觸發時執行進程調度(線程調度),並維護軟體時鐘。

PIT和RTC的區別:計算機中有一枚紐扣電池負責在關機時維持CMOS數據並驅動一個低頻時鐘,這個時鐘叫做實時鐘(Real-time clock),注意RTC是相當不精確的,所以大多數操作系統通常在開機之後維護一個軟體時鐘,通過時鐘中斷和網咯時間協議(http://www.ntp.org/)維護的軟體時鐘比RTC精確和可靠得多,絕大多數操作系統除了開機時會讀取RTC,關機時將RTC與軟體時鐘同步以外,大多數時間RTC都是孤獨地運行的。

PIT與WDT的區別:有些嵌入式MCU除了提供PIT以外還提供看門狗定時器(Watchdog timer),有些PIT可以用於WDT功能,有些WDT具有PIT功能,有些場合PIT和WDT可能使用相同的時鐘源,但兩者是不同的。PIT用於周期性產生中斷信號,而WDT一旦觸發,產生的是複位信號,嵌入式操作系統需要不停地重置WDT以阻止複位信號的產生,WDT主要用於從軟體錯誤中自動恢復。

嗯,實名反對另外…………不是咱不懂彆強答好么←_←

以上是硬體部分

當一個線程執行了sleep(1000)時,首先會陷入到內核態執行系統調用處理程序,相關的處理程序會設置一個軟體定時器(1000),然後轉向線程調度,這時候會進行線程上下文切換和進程上下文切換,線程調度程序將該線程標記為等待態,並標記該線程等待該定時器的信號,然後執行線程調度。

當時鐘中斷處理程序發現這個軟體定時器觸發時,便將這個信號量置位(或者複位?),然後通知線程調度模塊,線程調度發現這個信號量與某個線程相關聯,於是將線程標記為就緒態,這時候

{當前線程的優先順序更高:繼續執行當前進程,

當前進程是idle/當前線程優先順序低:轉向執行剛進入就緒態的線程並標記為當前線程,切換進程上下文,恢復保存的線程現場,然後把觸發的定時器和信號量參數傳遞給線程的內核態部分(系統調用處理程序),系統調用處理程序刪除定時器然後返回到用戶態}

sleep存在誤差的原因在於,你交出控制權以後,定時的時間到了你還能不能被分到時間片是未知數,所以有可能定時器時間到了線程並沒有馬上進入執行態,但是這個在pc上不是個事,伺服器才需要考慮這個

不過linux內核有個奇葩的東西叫做高解析度定時模式,和另外一個奇葩的東西叫做完全無滴答模式,在高解析度定時模式下,linux通過對PIT編程使得定時盡量精確(PIT的觸發周期是可調的,最低我記得小於微秒級,和CPU有關),這樣使得軟體定時器可以精確到微秒級,有時候在高精度定時模式下linux的時鐘中斷是完全沒有周期性的,每觸發一次時鐘中斷就要改一次定時周期。完全無滴答模式是把PIT直接關掉的,當然如果你有定時需求系統會把這玩意再打開。


其實很簡單,橋晶元裡面有WatchTimer也叫鐘錶定時器,一般主板是用32.768k晶振來轉出來。也有的主板會用主晶振轉出來,缺點就是費點電。然後cpu讀取寄存器得到時間值。這部分和單片機是一樣的。PC你可以認為就是更複雜的單片機,但是原理是相通的。sleep和單片機的不同,單片機的sleep是整體硬體進入到睡眠狀態(一般分幾級睡眠),而pc的是進入到軟睡眠,更像是堵塞進程狀態。這時另外一個用來當時間片的Timer還是在工作的,也就是說硬體沒有休息。通過計數然後跳出堵塞。其他命令以此類推就好了。PC也有真正的sleep命令,但是應用程序調不到,一般是由驅動來調的,用來完成休眠操作。這裡就不展開了,和單片機類似。


彙編裡面是不停地nop。底層要看CPU clk和 晶振頻率了。上面當然涉及到操作系統線程進程的suspend,resume之類的。


一句話,一般來言都是直接取一個本機時間。

本質跟家裡石英鐘沒區別,調用方法是讀取BIOS里存的時間,所以bios都需要一塊小電池存時間。

隨著現代電腦主頻的提升,精度略有提高,但基本用的還是石英晶振。

現在新系統聯網以後默認會通過網路修正誤差。語言一般調用系統介面,不直接訪問bios/uefi。

網路上跑網站的伺服器一般會用權威授時服務定期矯正。

深度閱讀http://www.cnblogs.com/ajianbeyourself/p/4189520.html

不是我寫的啊,讀過而已。

跟時鐘打交道最頭痛就是多線程與並發了。。哈哈哈。。


定時從不知道哪個硬體裡面拿 寫進只讀page 用戶態直接取就行了


推薦閱讀:

為什麼給cpu進行液氮冷卻不會熱脹冷縮而損壞?
[8] Python轉義字元和切片
深度學習:進化
昂貴的至強E5比同代i7貴在哪裡?
讓你用編程代碼表白,要怎麼寫呢?

TAG:操作系統 | 計算機科學 |