<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CPU 空閑時也在摸魚嗎?

          共 3423字,需瀏覽 7分鐘

           ·

          2021-03-26 18:52

          作者 | 碼農(nóng)的荒島求生

          人空閑時會發(fā)呆會無聊,計(jì)算機(jī)呢?

          假設(shè)你正在用計(jì)算機(jī)瀏覽網(wǎng)頁,當(dāng)網(wǎng)頁加載完成后你開始閱讀,此時你沒有移動鼠標(biāo),沒有敲擊鍵盤,也沒有網(wǎng)絡(luò)通信,那么你的計(jì)算機(jī)此時在干嘛?

          有的同學(xué)可能會覺得這個問題很簡單,但實(shí)際上,這個問題涉及從硬件到軟件、從 CPU 到操作系統(tǒng)等一系列環(huán)節(jié),理解了這個問題你就能明白操作系統(tǒng)是如何工作的了。


          你的計(jì)算機(jī) CPU 使用率是多少?

          如果此時你正在計(jì)算機(jī)旁,并且安裝有 Windows 或者 Linux ,你可以立刻看到自己的計(jì)算機(jī) CPU 使用率是多少。
          這是博主的一臺安裝有 Win10 的筆記本:
          可以看到大部分情況下 CPU 利用率很低,也就在 8% 左右,而且開啟了 283 個進(jìn)程,這么多進(jìn)程基本上無所事事,都在等待某個特定事件來喚醒自己,就好比你寫了一個打印用戶輸入的程序,如果用戶一直不按鍵盤,那么你的進(jìn)程就處于這種狀態(tài)。
          有的同學(xué)可能會想也就你的比較空閑吧,實(shí)際上大部分個人計(jì)算機(jī) CPU 使用率都差不多這樣(排除掉看電影、玩游戲等場景),如果你的使用率總是很高,風(fēng)扇一直在嗡嗡地轉(zhuǎn),那么不是軟件 bug 就有可能是病毒。。。
          那么有的同學(xué)可能會問,剩下的 CPU 時間都去哪里了?

          剩下的 CPU 時間去哪里了?
          這個問題也很簡單,還是以 Win10 為例,打開任務(wù)管理器,找到 “詳細(xì)信息” 這一欄,你會發(fā)現(xiàn)有一個 “系統(tǒng)空閑進(jìn)程”,其 CPU 使用率達(dá)到了 99%,正是這個進(jìn)程消耗了幾乎所有的 CPU 時間。
          那么為什么存在這樣一個進(jìn)程呢?以及這個進(jìn)程什么時候開始運(yùn)行呢?
          這就要從操作系統(tǒng)說起了。

          程序、進(jìn)程與操作系統(tǒng)
          當(dāng)你用最喜歡的代碼編輯器編寫代碼時,這時的代碼不過就是磁盤上的普通文件,此時的程序和操作系統(tǒng)沒有半毛錢關(guān)系,操作系統(tǒng)也不認(rèn)知這種文本文件。
          程序員寫完代碼后開始編譯,這時編譯器將普通的文本文件翻譯成二進(jìn)制可執(zhí)行文件,此時的程序依然是保存在磁盤上的文件,和普通的文本文件沒有本質(zhì)區(qū)別。
          但此時不一樣的是,該文件是可執(zhí)行文件,也就是說操作系統(tǒng)開始 “懂得” 這種文件,所謂 “懂得” 是指操作系統(tǒng)可以識別、解析、加載,因此必定有某種類似協(xié)議的規(guī)范,這樣編譯器按照這種協(xié)議生成可執(zhí)行文件,操作系統(tǒng)就能加載了。
          在 Linux 下可執(zhí)行文件格式為 ELF ,在 Windows 下是 EXE 。
          此時雖然操作系統(tǒng)可以識別可執(zhí)行程序,但如果你不去雙擊一下(或者在Linux下運(yùn)行相應(yīng)命令),依然和操作系統(tǒng)沒有半毛錢關(guān)系。
          但是當(dāng)你運(yùn)行可執(zhí)行程序時魔法就出現(xiàn)了。
          此時操作系統(tǒng)開始將可執(zhí)行文件加載到內(nèi)存,解析出代碼段、數(shù)據(jù)段等,并為這個程序創(chuàng)建運(yùn)行時需要的堆區(qū)棧區(qū)等內(nèi)存區(qū)域,此時這個程序在內(nèi)存中就是這樣了:
          最后,根據(jù)可執(zhí)行文件的內(nèi)容,操作系統(tǒng)知道該程序應(yīng)該執(zhí)行的第一條機(jī)器指令是什么,并將其告訴 CPU ,CPU 從該程序的第一條指令開始執(zhí)行,程序就這樣運(yùn)行起來了。
          一個在內(nèi)存中運(yùn)行起來的程序顯然和保存在磁盤上的二進(jìn)制文件是不一樣的,總得有個名字吧,根據(jù)“弄不懂原則”,這個名字就叫進(jìn)程,英文名叫做 Process。
          我們把一個運(yùn)行起來的程序叫做進(jìn)程,這就是進(jìn)程的由來
          此時操作系統(tǒng)開始掌管進(jìn)程,現(xiàn)在進(jìn)程已經(jīng)有了,那么操作系統(tǒng)是怎么管理進(jìn)程的呢?

          調(diào)度器與進(jìn)程管理
          銀行想必大家都去過,實(shí)際上如果你仔細(xì)觀察的話銀行的辦事大廳就能體現(xiàn)出操作系統(tǒng)最核心的進(jìn)程管理與調(diào)度。
          首先大家去銀行都要排隊(duì),類似的,進(jìn)程在操作系統(tǒng)中也是通過隊(duì)列來管理的。
          同時銀行還按照客戶的重要程度劃分了優(yōu)先級,大部分都是普通客戶;但當(dāng)你在這家銀行存上幾個億時就能升級為 VIP 客戶,優(yōu)先級最高,每次去銀行都不用排隊(duì),優(yōu)先辦理你的業(yè)務(wù)。
          類似的,操作系統(tǒng)也會為進(jìn)程劃分優(yōu)先級,操作系統(tǒng)會根據(jù)進(jìn)程優(yōu)先級將其放到相應(yīng)的隊(duì)列中供調(diào)度器調(diào)度。
          這就是操作系統(tǒng)需要實(shí)現(xiàn)的最核心功能。
          現(xiàn)在準(zhǔn)備工作已經(jīng)就緒。
          接下來的問題就是操作系統(tǒng)如何確定是否還有進(jìn)程需要運(yùn)行。

          隊(duì)列判空:一個更好的設(shè)計(jì)
          從上一節(jié)我們知道,實(shí)際上操作系統(tǒng)是用隊(duì)列來管理進(jìn)程的,那么很顯然,如果隊(duì)列已經(jīng)為空,那么說明此時操作系統(tǒng)內(nèi)部沒有進(jìn)程需要運(yùn)行,這是 CPU 就空閑下來了,此時,我們需要做點(diǎn)什么,就像這樣:
          if (queue.empty()) { do_someting();}
          這些編寫內(nèi)核代碼雖然簡單,但內(nèi)核中到處充斥著 if 這種異常處理的語句,這會讓代碼看起來一團(tuán)糟,因此更好的設(shè)計(jì)是沒有異常,那么怎樣才能沒有異常呢?
          很簡單,那就是讓隊(duì)列永遠(yuǎn)不會空,這樣調(diào)度器永遠(yuǎn)能從隊(duì)列中找到一個可供運(yùn)行的進(jìn)程。
          而這也是為什么鏈表中通常會有哨兵節(jié)點(diǎn)的原因,就是為了避免各種判空,這樣既容易出錯也會讓代碼一團(tuán)糟。
          就這樣,內(nèi)核設(shè)計(jì)者創(chuàng)建了一個叫做空閑任務(wù)的進(jìn)程,這個進(jìn)程就是 Windows 下的我們最開始看到的“系統(tǒng)空閑進(jìn)程”,在 Linux 下就是第 0 號進(jìn)程。
          當(dāng)其它進(jìn)程都處于不可運(yùn)行狀態(tài)時,調(diào)度器就從隊(duì)列中取出空閑進(jìn)程運(yùn)行,顯然,空閑進(jìn)程永遠(yuǎn)處于就緒狀態(tài),且優(yōu)先級最低。
          既然我們已經(jīng)知道了,當(dāng)系統(tǒng)無所事事后開始運(yùn)行空閑進(jìn)程,那么這個空閑進(jìn)程到底在干嘛呢?
          這就需要硬件來幫忙了。

          一切都要?dú)w結(jié)到硬件
          在計(jì)算機(jī)系統(tǒng)中,一切最終都要靠 CPU 來驅(qū)動,CPU 才是那個真正干活的。
          原來,CPU 設(shè)計(jì)者早就考慮到系統(tǒng)會存在空閑的可能,因此設(shè)計(jì)了一條機(jī)器指令,這個機(jī)器指令就是 halt 指令,停止的意思。
          這條指令會讓部分 CPU 進(jìn)入休眠狀態(tài),從而極大減少對電力的消耗,通常這條指令也被放到循環(huán)中執(zhí)行,原因也很簡單,就是要維持這種休眠狀態(tài)。
          值得注意的是,halt 指令是特權(quán)指令,也就是說只有在內(nèi)核態(tài)下 CPU 才可以執(zhí)行這條指令,程序員寫的應(yīng)用都運(yùn)行在用戶態(tài),因此你沒有辦法在用戶態(tài)讓 CPU 去執(zhí)行這條指令。
          此外,不要把進(jìn)程掛起和 halt 指令混淆,當(dāng)我們調(diào)用 sleep 之類函數(shù)時,暫停運(yùn)行的只是進(jìn)程,此時如果還有其它進(jìn)程可以運(yùn)行那么 CPU 是不會空閑下來的,當(dāng) CPU 開始執(zhí)行 halt 指令時就意味著系統(tǒng)中所有進(jìn)程都已經(jīng)暫停運(yùn)行。

          軟件硬件結(jié)合
          現(xiàn)在我們有了 halt 機(jī)器指令,同時有一個循環(huán)來不停地執(zhí)行 halt 指令,這樣空閑任務(wù)進(jìn)程實(shí)際上就已經(jīng)實(shí)現(xiàn)了,其本質(zhì)上就是這個不斷執(zhí)行 halt 指令的循環(huán),大功告成。
          這樣,當(dāng)調(diào)度器在沒有其它進(jìn)程可供調(diào)度時就開始運(yùn)行空閑進(jìn)程,也就是在循環(huán)中不斷地執(zhí)行 halt 指令,此時 CPU 開始進(jìn)入低功耗狀態(tài)。
          在 Linux 內(nèi)核中,這段代碼是這樣寫的:
          while (1) { while(!need_resched()) { cpuidle_idle_call(); }}
          其中 cpuidle_idle_call 函數(shù)最終會執(zhí)行 halt 指令,注意,這里刪掉了很多細(xì)節(jié),只保留最核心代碼,實(shí)際上 Linux 內(nèi)核在實(shí)現(xiàn)空閑進(jìn)程時還要考慮很多很多,不同類型的 CPU 可能會有深睡眠淺睡眠之類,操作系統(tǒng)必須要預(yù)測出系統(tǒng)可能的空閑時長并以此判斷要進(jìn)入哪種休眠等等,但這并不是我們關(guān)注的重點(diǎn)。
          總的來說,這就是計(jì)算機(jī)系統(tǒng)空閑時 CPU 在干嘛,就是在執(zhí)行這一段代碼,本質(zhì)上就是 CPU 在執(zhí)行 halt 指令。
          實(shí)際上,對于個人計(jì)算機(jī)來說,halt 可能是 CPU 執(zhí)行最多的一條指令,全世界的 CPU 大部分時間都用在這條指令上了,是不是很奇怪。

          總結(jié)
          CPU 空閑時執(zhí)行特定的 halt 指令,這看上去是一個很簡單的問題,但實(shí)際上由于 halt 是特權(quán)指令,只有操作系統(tǒng)才可以去執(zhí)行,因此 CPU 空閑時執(zhí)行 halt 指令就變成了軟件和硬件相結(jié)合的問題。
          操作系統(tǒng)必須判斷什么情況下系統(tǒng)是空閑的,這涉及到進(jìn)程管理和進(jìn)程調(diào)度,同時,halt 指令其實(shí)是放到了一個 while 死循環(huán)中,而且這個循環(huán)里沒有 break 句,也沒有 return,操作系統(tǒng)必須有辦法能跳出循環(huán),所以,CPU 空閑時執(zhí)行 halt 指令并沒有看上去那么簡單。
          希望這篇文章對大家理解 CPU 和操作系統(tǒng)有所幫助。
          瀏覽 84
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99久久精品互换人妻 | 殴美一级免费黄片 | 亚洲无码高清视频在线播放 | 日韩 欧美 亚洲 | 一级片免费不卡 |