一步步编写操作系统 44 用c语言编写内核1
先來個(gè)簡(jiǎn)單的,歡迎我們神秘嘉賓——main.c。這是我們第一個(gè)c語言代碼。
1 int main(void) { 2 while(1); 3 return 0; 4 }它沒法再簡(jiǎn)單啦,簡(jiǎn)單的程序似乎能幫助咱們更容易的理解所學(xué)的知識(shí),哈哈,我說的是似乎,其實(shí),再長(zhǎng)的代碼,編譯后生成的文件結(jié)構(gòu)也是由那幾個(gè)部分組成,萬變不離其宗。這里所說的文件結(jié)構(gòu)是指將來要說的elf文件格式,在此不多說,留作伏筆。
正如之前所說,咱們只有用c語言的語法結(jié)構(gòu),這里沒有包含標(biāo)準(zhǔn)庫,也沒有直接的系統(tǒng)調(diào)用,以后咱們都得按照這種簡(jiǎn)潔的方式編程啦。另外,有的同學(xué)已經(jīng)注意到main.c所在的目錄啦,本來我還是想賣個(gè)關(guān)子的,但它所在的目錄出賣了我:在kernel目錄下。對(duì),如您所想,它就是我們第一個(gè)內(nèi)核文件,我們?cè)趐roject目錄下建立了個(gè)子目錄kernel,今后我們所有與內(nèi)核相關(guān)的模塊都要放在此目錄下。
您也看到了,這個(gè)內(nèi)核文件什么都沒做,通過while(1)這個(gè)死循環(huán)一直空兜cpu,目的是停在這里。想當(dāng)初我就因?yàn)橥浖舆@樣的語句而導(dǎo)致不知道cpu執(zhí)行到哪去了,當(dāng)時(shí)排錯(cuò)時(shí)可暈頭了,看到執(zhí)行的指令都不是自己寫的,甚至都懷疑是虛擬機(jī)的問題,想想好慚愧啊,臉紅臉紅啊。當(dāng)然查出來原因之后,自然又是滿地打滾,喜極而泣啦。這個(gè)簡(jiǎn)單粗暴可依賴的死循環(huán)僅僅是為了演示elf文件解析以及加載內(nèi)核的作用,今后我們要逐步完善它,看著它一點(diǎn)一點(diǎn)長(zhǎng)大,就像是我們?cè)陴B(yǎng)育孩子一樣,盡管我還沒有結(jié)婚^_^。
生成c語言程序的過程是這樣的。先將源程序編譯成目標(biāo)文件(由c代碼變成匯編代碼后,再由匯編代碼生成二進(jìn)制的目標(biāo)文件),再將目標(biāo)文件鏈接成二進(jìn)制可執(zhí)行文件。平時(shí)我們寫只有一個(gè)文件的小程序時(shí),編譯器也是悄悄在背后這樣做的,除非加了參數(shù)讓編譯器分成兩個(gè)動(dòng)作。由于咱們用的是c語言寫的程序,想到的是編譯器自然是大名鼎鼎的gcc,所以我們用gcc編譯該程序的參數(shù)是:
gcc -c -o kernel/main.o kernel/main.c,也許對(duì)其中的參數(shù)有的同學(xué)不太熟,沒關(guān)系,在執(zhí)行g(shù)cc –help回車后,大家可以看到一些幫助信息,其中:
-c的作用是編譯、匯編到目標(biāo)代碼,不進(jìn)行鏈接,也就是直接生成目標(biāo)文件。
-o的作用是將輸出的文件以指定文件名來存儲(chǔ),有同名文件存在時(shí)直接覆蓋。
經(jīng)過上面gcc的編譯后,我們得到了main.o文件,目前為止,它還是個(gè)“半成品”。為什么這么說呢,因?yàn)樗皇莻€(gè)目標(biāo)文件,也稱為待重定位文件,重定位指的是文件里面所用的符號(hào)還沒有安排地址,這些符號(hào)的地址需要將來與其它目標(biāo)文件“組成”一個(gè)可執(zhí)行文件時(shí)再重新定位(編排地址),這里的符號(hào)就是指該目標(biāo)文件中所調(diào)用的函數(shù)或使用的變量,而這里的“組成”就是指鏈接。這些符號(hào)一般是位于其它文件中,所以在編譯時(shí)不能確定其地址,需要在所有目標(biāo)文件都到齊了,將它們鏈接到一起時(shí)再重新定位(編排地址)。由于不知道可執(zhí)行文件是由幾個(gè)目標(biāo)文件組成,所以一律在鏈接階段對(duì)符號(hào)重新定位(編排地址)。所以說,哪怕是可執(zhí)行文件只是由一個(gè)文件組成,其目標(biāo)文件中的符號(hào)也是未編址的,編址工作,即重定位,一律統(tǒng)一在鏈接階段完成。
編譯成目標(biāo)文件時(shí)也不我們可以用file命令檢查一下main.o的狀態(tài)。如file kernel/main.o,輸出見圖
為了讓大家更明顯地看出目標(biāo)文件的可重定位屬性,我將relocatable用方框給大家圈出來了。
目標(biāo)文件是可重定位文件,其中的符號(hào)都尚未“定位”,也就是符號(hào)(變量名,函數(shù)名)的地址尚未確定,這一點(diǎn)我們可以用linux的nm命令來查看。如圖
如圖所見,由于咱們的main.c過于簡(jiǎn)單,里面只有一個(gè)符號(hào),即main,所以nm只列出了它的符號(hào)信息。main函數(shù)的地址由于未被指定,所以其值為00000000。一會(huì)咱們鏈接后再對(duì)比下大家就更清楚了.
總結(jié)
以上是生活随笔為你收集整理的一步步编写操作系统 44 用c语言编写内核1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】聊聊分布式事务,再说说解决方案
- 下一篇: 河南此轮地表最高温度达74.1℃ 轻松煎