計算機的 CPU、操作系統(tǒng)與內(nèi)存管理
本文轉(zhuǎn)載自微信公眾號「神光的編程秘籍」,作者神說要有光zxg。轉(zhuǎn)載本文請聯(lián)系神光的編程秘籍公眾號。
一些關(guān)于計算機原理的思考,大家隨意看看就行。
硬布線到馮諾伊曼
其實最早的計算機是沒有存儲機制的,都是通過硬布線來編程,編程就是布線,后來的電子計算機有了存儲的機制,能夠存儲一些指令和數(shù)據(jù),這樣就有了能夠復(fù)用的程序的存在基礎(chǔ),通過電和磁來存儲二進(jìn)制信息,替代掉了硬布線。
計算機之所以能存儲是因為它是圖靈機模型的實現(xiàn),存儲的部分對應(yīng)了圖靈機模型中的紙帶,馮諾伊曼體系結(jié)構(gòu)(現(xiàn)代計算機的體系結(jié)構(gòu))是圖靈機的實現(xiàn),它設(shè)計了用二進(jìn)制表示機器碼、存儲以及計算機五大部件:輸入、輸出、控制、運算、存儲。
現(xiàn)在的計算機有 cpu 內(nèi)的寄存器和 L1、L2、L3 緩存 ,還有內(nèi)存和硬盤的存儲方式,這 6 級存儲介質(zhì)就是計算機的存儲體系。計算機發(fā)展到現(xiàn)在的存儲體系,存儲已經(jīng)是一個常識了。存儲是程序復(fù)用的基礎(chǔ),可以重復(fù)執(zhí)行一些編寫好的代碼。而且編譯的出現(xiàn)和發(fā)展,使得我們不用輸入機器碼,可以用字符構(gòu)成的高級語言編程,然后編譯為二進(jìn)制的機器語言。
cpu 與時鐘和 jump
程序最終是 cpu 執(zhí)行的,而 cpu 執(zhí)行什么指令是由 CS + IP 寄存器控制,cpu 會不斷的取這倆寄存器所表示的內(nèi)存地址的指令,通過數(shù)據(jù)總線讀入 cpu,用譯碼器譯碼之后用不同電路執(zhí)行。取指令、譯碼、執(zhí)行指令,這是 cpu 的一個始終周期,cpu 會無限循環(huán)這個過程,指令周期的執(zhí)行頻率受時鐘控制,有一定的頻率,有的計算機可以支持短時間的超頻,就是提高了這個時鐘的頻率。cpu 是不斷循環(huán)時鐘周期的,那么總要有個初始地址,這個地址一般是固定的地址,放計算機通電以后加載的第一條指令,這部分代碼叫做 BIOS(基礎(chǔ)輸入輸出系統(tǒng)),它是后續(xù)一切程序執(zhí)行的基礎(chǔ)。指令支持跳轉(zhuǎn)到另一個地址,通過這種方式支持了控制流。就像前面所說,cpu 是不斷循環(huán)時鐘周期的,那么總要有種方式來控制它轉(zhuǎn)向,控制轉(zhuǎn)向的功能就是通過跳轉(zhuǎn)指令, 所以說 jump 指令是 cpu 的方向盤。而指令和數(shù)據(jù)可以放在內(nèi)存的任何位置,通過 jump 的方向盤控制 cpu 跑到那里。
cpu 是一輛汽車,那么時鐘就是引擎,控制著 cpu 執(zhí)行指令的頻率,而執(zhí)行到哪條指令是存在 CS + IP 寄存器里的,它只會往前開,也就是只會不斷的取下一條指令,而轉(zhuǎn)向(也就是控制流)是由 jump 指令控制的,跑到內(nèi)存中的任何地方取指令來到 cpu 上跑,而最開始的一段路就是 BIOS 程序所在的地方。
BIOS、裸機和操作系統(tǒng)
BIOS 程序其實一般不會自己寫,除非做嵌入式,直接在裸機(沒有操作系統(tǒng)的計算機)上開發(fā),那需要自己做程序的引導(dǎo),自己可以控制把指令存在哪,數(shù)據(jù)存在哪,從哪里取。這種邏輯太過通用,而且只有一個控制流,只有一條路線和風(fēng)景,不能充分利用 cpu ,為了解決這個問題,出現(xiàn)了操作系統(tǒng),它能多到多個控制流,也就是汽車有多條行進(jìn)路線,可以看到不同的風(fēng)景。
操作系統(tǒng)也有自己的 BIOS 程序,是 cpu 最開始的一段路,把 cpu 帶到操作系統(tǒng)所在的地方,操作系統(tǒng)一般都提供了進(jìn)程的機制,也把內(nèi)存管理了起來,不再是隨意的亂用,而是需要需要申請,就像我們企業(yè)內(nèi)會把管理起來的東西做審批流一樣,申請之后才會分配內(nèi)存,進(jìn)程的程序就放在這塊內(nèi)存上。邏輯是一條控制流,進(jìn)程則是可以有多條控制流,雖然一輛汽車(一個 cpu)只能同時跑一個地方,但是卻可以在其它代碼不需要它的時候去給別的進(jìn)程跑跑,就像順風(fēng)車一樣不用的時候帶帶別人一樣。cpu 不是一直在跑么,為啥會有不用它的時候,因為磁盤或者網(wǎng)卡等設(shè)備都有自己的控制器,叫做 DMA,當(dāng)跑到那個地方的時候,會讓 DMA 去搬運東西,就像叫了貨拉拉但自己搬東西一樣。當(dāng) DMA 搬運設(shè)備數(shù)據(jù)到內(nèi)存的過程中,cpu 需要等,就閑下來了。這時候不如去跑跑別的代碼,當(dāng)然也可以啥也不干就等在那(阻塞的等待)。cpu 是可以在 io 的時候跑別的代碼,跑的路線叫做控制流,控制流也有兩種類型,一種是進(jìn)程、一種是線程,線程可以訪問進(jìn)程分配的內(nèi)存等資源,而不同進(jìn)程有各自的分配的資源,不能互相訪問,需要用其他內(nèi)存來做中轉(zhuǎn)。
我們知道,裸機時程序可以訪問和操作所有內(nèi)存,由程序自己控制,但是有了操作系統(tǒng),就要遵循操作系統(tǒng)的規(guī)范了,操作系統(tǒng)對于可執(zhí)行文件有格式的要求,只有一定的格式才能作為機器碼來執(zhí)行,windows 上是 exe 格式,linux 等系統(tǒng)上是 elf 格式。elf 格式會把文件分為代碼段 (text)、數(shù)據(jù)段(data)等不同的部分,來放不同的數(shù)據(jù),這樣文件加載到內(nèi)存中會放在不同的地方,然后會從 text 段取代碼執(zhí)行,從 data 段取全局?jǐn)?shù)據(jù),運行時還有調(diào)用棧和堆所占用的內(nèi)存。不同進(jìn)程在各自的內(nèi)存上加載自己的可執(zhí)行文件,然后在執(zhí)行時會形成不同的控制流,會在棧和堆上放不同的數(shù)據(jù)。這是受操作系統(tǒng)限制的內(nèi)存管理,由操作系統(tǒng)決定,相比裸機少了一些自由(必須做成可執(zhí)行文件的格式),但多了各種操作系統(tǒng)提供的能力(系統(tǒng)調(diào)用和標(biāo)準(zhǔn)庫)。
操作系統(tǒng)和 vm 的內(nèi)存管理
操作系統(tǒng)給可執(zhí)行文件跑起來的進(jìn)程分配了內(nèi)存,然后這個進(jìn)程可以內(nèi)部再做劃分,比如 vm,會在自己的內(nèi)存上再做一次內(nèi)存管理,各種解釋型語言就是跑在這塊內(nèi)存上,因為自己管理,就不用不同操作系統(tǒng)有不同的內(nèi)存格式了,可以統(tǒng)一成一種(能跨平臺)。比如 jvm 有方法區(qū)、靜態(tài)域、堆、棧等等, 而 js vm 有全局作用域(類似靜態(tài)域)、調(diào)用棧(函數(shù)上下文的棧)、堆等。這些 vm 因為自己又做了一層內(nèi)存管理,所以上面跑的字節(jié)碼等受到的內(nèi)存管理方式不是操作系統(tǒng)的,而是 vm 自己設(shè)計的。但是不管怎么設(shè)計,總還是要存放代碼、數(shù)據(jù)的,動態(tài)分配基本都是在堆上,全局?jǐn)?shù)據(jù)放靜態(tài)域,有調(diào)用棧維護(hù)上下文,這個基本是通用的設(shè)計了。
內(nèi)存管理主要是管理代碼和數(shù)據(jù)在內(nèi)存某個位置的寫入和修改,通過變量的方式引用某塊內(nèi)存,不同的變量類型引用不同大小的內(nèi)存。從裸機上的隨意修改內(nèi)存,到操作系統(tǒng)上進(jìn)程受限制的操作內(nèi)存,再到 vm 上對內(nèi)存做的進(jìn)一步設(shè)計。不同層次都會做自己的設(shè)計,但是總歸是交給 cpu 來跑的,當(dāng) cpu 跑到這塊內(nèi)存,用 jump 來控制轉(zhuǎn)向,同時利用操作系統(tǒng)提供的線程能力,可以跑不同的路線(控制流)。
總結(jié)
本文主要是梳理了一些計算機的歷史和原理,從硬布線到馮諾伊曼體系,到 6 級的存儲體系的發(fā)展過程是發(fā)展歷史的部分,而 cpu 的指令周期與時鐘頻率是 cpu 的工作方式,cpu 不斷執(zhí)行指令周期,跳到別的地方(改變控制流)是通過 jump 指令實現(xiàn)的,上層高級語言基于 jump 封裝出了 if、else、函數(shù)調(diào)用等。
計算機最開始執(zhí)行的引導(dǎo)程序是 BIOS,裸機和操作系統(tǒng)都需要,操作系統(tǒng)提供了進(jìn)程管理的能力,可能同時有多個控制流,而且提供了各種軟硬件管理能力,暴露了系統(tǒng)調(diào)用和標(biāo)準(zhǔn)庫。操作系統(tǒng)可以加載一定格式的可執(zhí)行文件,不同系統(tǒng)有自己的進(jìn)程的內(nèi)存管理方式,而 vm 則是在操作系統(tǒng)分配的內(nèi)存上自己做了一層內(nèi)存管理,現(xiàn)在很多跨平臺軟件都是基于這種跑在 vm 上的語言的。雖然不同 vm 的內(nèi)存管理的設(shè)計有不同,但堆棧等設(shè)計確是通用的。
注:雖然我們做前端開發(fā)不需要了解太多計算機原理,但是理解計算機是提升內(nèi)功,內(nèi)功提升了,做任何開發(fā)都會有更深入的認(rèn)識。這篇是隨便寫的一些想法,希望能拋磚引玉,引起大家對計算機原理的一些思考。