標籤:
從本質上來說作業系統就是把底層硬體抽象成了一層虛擬機器,所以說電腦本身就是一個虛擬機器。電腦本身並不會做任何事情,它就是一堆鐵疙瘩,即使給它加電它也不會做任何事情,cpu只有在程式的指揮下才會做事情。所以,作業系統的啟動就是一個自舉的過程,上電的一刹那間主板上的一塊ROM晶片中的代碼會被自動對應到記憶體的低地址空間,這塊ROM晶片中存的就是BIOS,後續的過程可以參見我的另一篇部落格http://jiuyugu.blogspot.com/2016/03/blog-post.html,本文不做詳細討論。
在馮諾依曼體系中,電腦有五大組件,分別是運算器、控制器、儲存空間、輸入裝置和輸出裝置。其中最核心的是運算器、控制器和儲存空間。運算器在控制器的控制下從不斷從儲存空間中讀取資料處理,在電腦內部的儲存空間速度是最快的,稱為寄存器,之所以稱為寄存器是因為只裡面的資料重新整理頻率很快,然後是一級緩衝、二級緩衝、三級緩衝,再到外面就是記憶體了,從內到外造價越來越低,存取速度越來越慢,容量越來越大。這裡牽扯到一個問題,為什麼緩衝可以提高速度? 程式的局部性原理,就是我們常說的二八法則,一段程式中執行頻率最高的代碼往往只有20%,80%的代碼很少用到,而這20%的程式碼完成了整個程式80%的功能。我們可以將這20%的代碼緩衝到cpu一級緩衝或者二級緩衝中,因為cpu中的cache的速度和cpu的時鐘頻率最接近,這樣就可以提高程式啟動並執行速度,關於這部分的詳細介紹可以參見《深入理解電腦系統》一書。在我的debian系統上可以用lscpu指令查看有關cpu和cache的簡略資訊:可以看到從L1 cache到L3 cache,容量越來越小了
1 [email protected]:~$ lscpu 2 Architecture: x86_64 3 CPU op-mode(s): 32-bit, 64-bit 4 Byte Order: Little Endian 5 CPU(s): 4 6 On-line CPU(s) list: 0-3 7 Thread(s) per core: 2 8 Core(s) per socket: 2 9 Socket(s): 110 NUMA node(s): 111 Vendor ID: GenuineIntel12 CPU family: 613 Model: 4214 Model name: Intel(R) Core(TM) i5-2430M CPU @ 2.40GHz15 Stepping: 716 CPU MHz: 825.75017 CPU max MHz: 3000.000018 CPU min MHz: 800.000019 BogoMIPS: 4789.1420 Virtualization: VT-x21 L1d cache: 32K22 L1i cache: 32K23 L2 cache: 256K24 L3 cache: 3072K25 NUMA node0 CPU(s): 0-3
一般緩衝演算法設計的思路都是:最近最少使用原則,將最近最少使用的資料從緩衝中移除,畢竟緩衝的空間是有限的,要是緩衝和記憶體的價格一樣,那就沒必要設計緩衝了。程式的局部性原理分為空白間局部性和時間局部性:空間局部性是指一段代碼被訪問了,那麼它周圍的代碼也極有可能被訪問到。時間局部性是指某一時刻一段代碼被訪問了,那麼過一會兒這段代碼極有可能被再次訪問。
為了銜接電腦系統中各個速度比cpu慢的裝置,早期的主板上整合有北橋晶片和南橋晶片(現在的主板可能已經不是這麼設計了),南橋晶片是將各慢速裝置匯總起來一起接入北橋晶片,所以橋接晶片說白了就是匯總各外部裝置最終完成和cpu的互動。south bridge上接的通常稱為ISA匯流排,早起的PCI匯流排都是接到南橋上的,接入北橋的稱為PCI--E,PCI--E匯流排的速度比PCI匯流排的速度要快得多得多。常見的磁碟匯流排都是PCI格式的,SCSI、IDE、SATA統稱為PCI匯流排,PCI只是一種統稱。那麼問題來了,電腦接了這麼多的外部裝置,cpu如何區分不同的IO裝置呢? 類比電腦區分和互連網通訊的各個進程的方法,電腦區分不同的和外部通訊的進程靠的是通訊端,也就是ip地址+連接埠號碼。這裡cpu區分不同IO裝置靠的也是連接埠號碼,稱為IO連接埠,在一台電腦上IO連接埠的數目也是65535個。任何一個IO裝置通過IO匯流排接入電腦的時,它必須一開機就申請一批連續的IO連接埠。
之所以把作業系統稱為虛擬機器,是因為我們只有一塊cpu晶片(可能是多核心的),只有一塊記憶體,滑鼠只有一個,鍵盤只有一個........但是每個進程都好像獨佔這一整套資源。cpu通過時間片輪轉的方式講一個cpu晶片虛擬成多個cpu,記憶體的虛擬通過分頁機制,將記憶體切割成一個個固定大小的頁面(這部分參見我的另一篇部落格http://jiuyugu.blogspot.com/2016/03/linux.html 以及《程式員的自我修養--連結、裝載與庫》)。好了,現在已經把電腦系統中最重要的兩個組件運算器和儲存空間虛擬出來了(其實就是虛擬cpu和記憶體),剩下的那些IO裝置如何虛擬呢?其實在IO虛擬不需要專門去做,因為當前哪個進程獲得了系統使用權,IO裝置就交給整個進程。
cpu晶片只有一塊,在某一時刻,要麼是核心進程在上面運行,要麼是使用者空間進程在上面運行,核心在cpu上運行時稱為核心模式,進程在cpu上運行時稱為使用者模式。而在記憶體中核心佔據的那段記憶體空間稱為核心空間,使用者進程佔據的空間叫使用者空間。使用者模式時,進程是不能直接控制硬體的。這是因為在cpu內部,cpu製造商將cpu能啟動並執行指令劃分為4層(僅對x86架構而言),ring0,ring1,ring2,ring3,由於曆史原因,ring1和ring2並沒有使用,linux只用了ring0和ring3。ring0稱為核心模式,也稱為特權指令模式,可以直接操控硬體,ring3是使用者模式,可以執行一般指令。
當一個運行中的進程要開啟檔案或者操作麥克風,它發現自己沒有許可權執行特權指令,於是就會發起系統調用,一旦產生系統調用進程就會退出,從使用者模式切換到特權模式,稱為模式切換。由核心負責將資料轉載至實體記憶體,再複製到使用者空間。這裡就牽扯到進程的狀態了,這裡簡單介紹幾個。就緒狀態:就緒是指在所有進程隊列中,這個進程所需的所有資源都已經準備好了。沒有就緒的稱為睡眠狀態,而睡眠狀態又分為可中斷睡眠和不可中斷睡眠,他倆的區別是:可中斷睡眠是指隨時可以喚醒的,不可中斷睡眠是指核心為它準備的資料還沒有準備好,即使喚醒它,它也不能幹活。可中斷睡眠不是因為資源沒有準備好而睡眠,只是一個階段的活兒幹完了,下一階段的活兒還沒來,於是它就去睡覺了,你可以隨時叫醒它,所以稱可中斷睡眠。而不可中斷睡眠一般是因為IO而進入睡眠狀態的。
電腦基本原理