操作系統(tǒng)被稱為“第一個(gè)程序”,the first programme,原因很簡(jiǎn)單,只有當(dāng)操作系統(tǒng)啟動(dòng)起來后才能運(yùn)行我們編寫的程序,那么你有沒有想過這個(gè)問題:操作系統(tǒng)是怎樣啟動(dòng)起來的呢? 實(shí)際上這個(gè)過程就像發(fā)射火箭一樣有趣 ,看完這篇你就明白啦。
操作系統(tǒng)也是普通程序
哦對(duì)了,順便說下,小風(fēng)哥建了一個(gè)微信技術(shù)群,感興趣的同學(xué)可以加一下,拉到最后掃描二維碼備注“加群”即可。
首先我們必須意識(shí)到這樣兩點(diǎn):
- CPU執(zhí)行的是機(jī)器指令,編譯器將程序翻譯后成了機(jī)器指令
- 操作系統(tǒng)本身也是一個(gè)程序,這個(gè)程序被編譯后也會(huì)生成一大堆機(jī)器指令
現(xiàn)在我們知道了,操作系統(tǒng)本身其實(shí)也是一大堆機(jī)器指令,既然是機(jī)器指令那么它必須得存放在什么地方。
存放在哪里呢?
想想我們編寫的程序,編譯后生成的是可執(zhí)行文件,也就是說是以“文件”的形式存放的,并且存放在硬盤上,而操作系統(tǒng)也沒什么不同,編譯后生成的機(jī)器指令同樣是以文件的形式存放的,存放在哪里呢?可以存放在任何能存儲(chǔ)數(shù)據(jù)的介質(zhì),像CD、磁盤之類都可以。
我們編寫的程序在啟動(dòng)時(shí)被加載器——也就是loader,加載到內(nèi)存,加載器也是一個(gè)程序,這是一個(gè)加載其它程序的程序;這么說可能有點(diǎn)拗口,但計(jì)算機(jī)系統(tǒng)中有大量類似的程序,編譯器是一個(gè)翻譯程序的程序、操作系統(tǒng)是一個(gè)運(yùn)行其它程序的程序、鏈接器是一個(gè)鏈接程序的程序、解釋器是一個(gè)執(zhí)行腳本程序的程序等等。
雞生蛋蛋生雞的問題
回到我們的主題,我們寫的代碼是loader加載到內(nèi)存后運(yùn)行的,那么操作系統(tǒng)這個(gè)程序是也同樣的道理,必須得有個(gè)什么東西也要把操作系統(tǒng)加載到內(nèi)存中運(yùn)行才可以,這個(gè)東西不叫l(wèi)oader,而是叫boot loader,其本身也是一個(gè)程序, 它的任務(wù)就是加載一個(gè)更大的程序 ,就像這里的操作系統(tǒng)。
此時(shí)這里會(huì)出現(xiàn)一個(gè)雞生蛋蛋生雞的,既然我們的程序是被加載器loader(操作系統(tǒng)的一部分)加載到內(nèi)存中,而操作系統(tǒng)又是被boot loader這個(gè)加載程序加載到內(nèi)存中的,那么又是什么加載器把boot loader這個(gè)加載程序加載到內(nèi)存中呢?而又又是什么加載器把上一句中的什么加載器加載內(nèi)存中呢?而又又又是什么。。?
你會(huì)發(fā)現(xiàn)這個(gè)一個(gè)沒有出口的無窮遞歸啊有沒有,總得有個(gè)什么把前一個(gè)程序加載到內(nèi)存, 就好比今天的前一天是昨天、昨天的前一天是前天、前天的前一天是大前天,如果一直這樣思考下去那么時(shí)間到底在哪里開始的呢 ?時(shí)間到底有沒有開始(參考時(shí)間簡(jiǎn)史或相對(duì)論)?
時(shí)間有沒有開始這個(gè)問題我不清楚,但操作系統(tǒng)啟動(dòng)的這個(gè)問題我知道。
上述關(guān)于加載器以及加載加載器等問題全部指向了內(nèi)存,讓我們好好想一想內(nèi)存有什么特殊性?
內(nèi)存斷電后是無法保存數(shù)據(jù)
程序員都知道內(nèi)存只有在加電的情況下才可以保存數(shù)據(jù),那么很顯然, 當(dāng)斷電后內(nèi)存中的內(nèi)容就丟失了 ,那么又很顯然的,當(dāng)你在按下計(jì)算機(jī)開關(guān)通電時(shí),內(nèi)存中的內(nèi)容是未被初始化的,也就是說內(nèi)存中的內(nèi)容是無效的, 此時(shí)的內(nèi)存里還是一片荒蕪 ,這里沒有任何東西可供CPU來執(zhí)行,這就好比大爆炸之前的宇宙。
但我們的計(jì)算機(jī)總是能啟動(dòng)起來,CPU必須得執(zhí)行“一段什么程序”把第一個(gè)boot loader加載到內(nèi)存中, 由于此時(shí)內(nèi)存中還什么都沒有,那么這段程序一定被保存在了其它地方 。
保存在了哪里呢?
沒錯(cuò),這段程序就被保存在了BIOS的非易失性存儲(chǔ)ROM或者flash存儲(chǔ)中了,這里的代碼在即使斷電后也會(huì)保存下來,加電后CPU開始執(zhí)行這里代碼,把boot loader加載到內(nèi)存中,現(xiàn)在你應(yīng)該明白第一個(gè)boot loader是怎樣被加載到內(nèi)存的了吧。
在早期的計(jì)算機(jī)上甚至專門有一個(gè)按鈕,讓用戶自己選擇該從哪里,比如打孔紙帶、打孔卡片或者硬盤,加載一個(gè)更復(fù)雜的程序來運(yùn)行,操作面板上的旋鈕可以控制把這些程序加載到內(nèi)存的什么位置上去:
火箭與操作系統(tǒng)啟動(dòng)
然而現(xiàn)實(shí)情況比較復(fù)雜,我們剛才提到的boot loader這段小程序功能實(shí)在是太弱了,此時(shí)其能訪問的磁盤地址空間有限,不能把完整的內(nèi)核全部加載到操作系統(tǒng)中,該怎么辦呢?
既然boot loader比較弱那么就換一個(gè)比較牛的loader程序來,就這樣出現(xiàn)了二階boot loader,second stage loader:
二階boot loader功能更為豐富,比如對(duì)硬件進(jìn)行檢查、給用戶提供選項(xiàng)加載哪個(gè)操作系統(tǒng)等等,安裝多系統(tǒng)的同學(xué)應(yīng)該知道,啟動(dòng)時(shí)會(huì)給你一個(gè)選項(xiàng)到底是啟動(dòng)windows還是linux,這就是二階boot loader的作用。
最終,操作系統(tǒng)被二階boot loader加載到內(nèi)存中開始運(yùn)行。
你會(huì)發(fā)現(xiàn)這個(gè)過程就和發(fā)射三級(jí)火箭一樣,最初一級(jí)火箭啟動(dòng),燃料用盡后二級(jí)火箭啟動(dòng),二級(jí)火箭完成使命后三級(jí)火箭啟動(dòng),最終把衛(wèi)星送到太空,而計(jì)算機(jī)的啟動(dòng)過程也類似。
最初是CPU運(yùn)行BIOS中的一段代碼把一級(jí)boot loader加載到內(nèi)存中運(yùn)行,該程序又會(huì)把二級(jí)boot loader加載到內(nèi)存運(yùn)行,而二級(jí)boot loader又會(huì)把操作系統(tǒng)加載到內(nèi)存中,此后控制權(quán)被轉(zhuǎn)移到操作系統(tǒng),(所謂控制權(quán)是指CPU跳轉(zhuǎn)到操作系統(tǒng)的代碼),操作系統(tǒng)開始運(yùn)行,經(jīng)過一系列的初始化,比如硬件檢測(cè)、開啟必要的后臺(tái)進(jìn)程等等,最終圖形界面或者命令行界面呈現(xiàn)出來。
接下來我們把這個(gè)過程細(xì)化一下。
更詳細(xì)的啟動(dòng)過程
你在按下電源的瞬間相當(dāng)于火箭點(diǎn)火,此時(shí)一級(jí)發(fā)動(dòng)機(jī)開始工作。
加電CPU重置后開始在地址0xffff0處開始執(zhí)行指令,這個(gè)地址其實(shí)是BIOS ROM的末尾處,該位置其實(shí)是一個(gè)跳轉(zhuǎn)指令,跳轉(zhuǎn)到ROM的一段啟動(dòng)代碼上,該代碼會(huì)進(jìn)行必要的自檢,Power-on self-test (POST),展示BIOS啟動(dòng)界面等等,最重要的一步是找到啟動(dòng)設(shè)備,所謂啟動(dòng)設(shè)備就是指從哪里加載操作系統(tǒng),比如CD-ROM、或者磁盤、甚至U盤等都可以作為啟動(dòng)設(shè)備,早些年流行用U盤重新安裝系統(tǒng),其實(shí)就是告訴BIOS的這段代碼從U盤中加載操作系統(tǒng)。
通常BIOS會(huì)把磁盤當(dāng)做啟動(dòng)設(shè)備(大部分情況下),此時(shí)BIOS中的這段代碼開始將磁盤的第0號(hào)塊加載到內(nèi)存中,那么這第0號(hào)塊中有什么呢?沒錯(cuò),就是第一階段boot loader程序,這第0號(hào)塊也被稱之為Master Boot Record,MBR,肯定有不少同學(xué)聽說過。
到這里,火箭的一級(jí)發(fā)動(dòng)機(jī)燃料用盡,二級(jí)發(fā)動(dòng)機(jī)開始點(diǎn)火,BIOS中的這段代碼把控制權(quán)交給加載到內(nèi)存boot loader,所謂控制權(quán)就是跳轉(zhuǎn)到boot loader程序,這樣CPU終于開始直接與內(nèi)存交互了,CPU開始從內(nèi)存中取出指令然后執(zhí)行。
MBR中除了包含一段可執(zhí)行代碼之外還有一個(gè)分區(qū)表,partition table,這個(gè)表的中的每一個(gè)條目本質(zhì)上在說:“操作系統(tǒng)是否在我這個(gè)分區(qū),我這個(gè)分區(qū)有多大”,CPU在執(zhí)行MBR中的代碼時(shí)會(huì)去檢查操作系統(tǒng)存在哪個(gè)分區(qū)中,定位后開始從相應(yīng)分區(qū)的起始位置讀取磁盤數(shù)據(jù)到內(nèi)存中,這時(shí)的磁盤數(shù)據(jù)中保存的就是二階boot loader,second-stage boot loader,此時(shí)一階boot loader把控制權(quán)轉(zhuǎn)交給二階boot loader,火箭三級(jí)發(fā)動(dòng)機(jī)開始工作。
2_boot loader的主要工作將操作系統(tǒng)加載到內(nèi)存中,此后控制權(quán)轉(zhuǎn)交給操作系統(tǒng),火箭的三級(jí)發(fā)動(dòng)機(jī)完成使命, 到這一時(shí)刻,操作系統(tǒng)開始接管計(jì)算機(jī) ,操作系統(tǒng)經(jīng)過一系列自身的初始化后創(chuàng)建出若干必要進(jìn)程,至此計(jì)算機(jī)啟動(dòng)完畢,衛(wèi)星被成功送到了外太空中。
然而限于篇幅這里依然沒有過多涉及細(xì)節(jié),操作系統(tǒng)本身的初始化也是一個(gè)比較復(fù)雜的過程,感興趣的同學(xué)可以去翻閱相關(guān)操作系統(tǒng)的資料。
總結(jié)與腦洞
計(jì)算機(jī)的啟動(dòng)是一個(gè)多階段的過程,當(dāng)然在一些嵌入式設(shè)備等這個(gè)過程會(huì)簡(jiǎn)化,但總體上也需要經(jīng)過類似過程,只不過階段數(shù)會(huì)少一些。
回到最開始的那個(gè)問題,也就是時(shí)間有沒有開始,其實(shí)這個(gè)問題一些物理大牛已經(jīng)回答過了, 但我很想在這里開一個(gè)腦洞 ,當(dāng)上帝在為自己創(chuàng)建的宇宙(計(jì)算機(jī))加電的那一刻——也就是宇宙大爆炸時(shí),時(shí)間開始了,時(shí)間這個(gè)概念是和宇宙(計(jì)算機(jī))相伴相生的,如果沒有宇宙(計(jì)算機(jī)),時(shí)間這個(gè)概念其實(shí)是沒有意義的,就好比如果沒有計(jì)算機(jī),加載這個(gè)概念其實(shí)是沒有意義的, 你思考時(shí)間到底有沒有起點(diǎn)這個(gè)問題就好比計(jì)算機(jī)中的程序在思考到底是誰把自己加載到內(nèi)存的、又是誰把操作系統(tǒng)加載到內(nèi)存中的等等 。。好啦,腦洞就開到這里。
現(xiàn)在你應(yīng)該明白計(jì)算機(jī)啟動(dòng)這個(gè)問題了吧
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6801瀏覽量
123283
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論