歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux 0.11 在Ubuntu-11和gcc-4.6.1下編譯調試至正常運行的過程詳解

Linux 0.11 在Ubuntu-11和gcc-4.6.1下編譯調試至正常運行的過程詳解

日期:2017/2/28 15:53:07   编辑:Linux教程

引言

1、 工作背景

研究linux-0.11已有月余,代碼看了好幾遍,雖然能看懂,卻總感覺如隔靴搔癢一般。這當然是正常的,畢竟不是自己寫的東西,畢竟這是個操作系統。但若能親自修改並調試一番,對其的理解就能更加深刻了。然而在linux-0.11的編譯要在裝有gcc1.4的系統裡進行,那個系統太老了,修改起來也不方便,又沒法安裝源碼閱讀器. . . 那能不能在Ubuntu下用高版本的gcc編譯並運行呢?

2、 工作意義

簡單講下本文所描述工作以及撰寫本文的意義吧。

Linux-0.11在高版本gcc-4.6.11下編譯調試並能正常運行可以使學習linux-0.11更加方便、容易,也為進一步研究linux2.6奠定基礎。更加重要的是,本項工作的過程其實就是一個深入學習的過程,對了解新舊版本gcc之間的差異、linux內核運行機制、linux調試方法有很大幫助。另外,對於linux-0.11在高版本gcc下的編譯工作,網上已有不少先驅者,但大都沒能讓編譯過後的os正常運行起來,偶有高人完成,也未能提供足夠的調試材料,這讓不少初學者對此失去了興趣。現在有興趣於此的大哥mm們High起來吧!

當然這項工作在很多人眼裡並沒多重要,他們認為它一沒有科研創新價值,而沒有商業盈利價值,還耗費不少時間,他們有更重要的事情去做。這個浮躁的社會裡,人們做什麼事情總要講究足夠的理由。對此我只能說,你們是沒錯的。

然我道中人終究還有不少,撰寫本文也是希望跟我相同想法的人能從中獲得他們需要的幫助,並借此與他們互相勉勵一下。有句老話怎麼說來著?重要的不是目的地,而是沿途的風景。

當然若有高人前輩路過,願意批評指正的,望不吝賜教,我將不甚感激涕零。

3、工作目的:

本文工作的目的在ubuntu-11中使用gcc-4.61成功編譯linux-0.11源碼,並經過調試使之能正常運行。由於時間關系,並未解決系統中所有存在的bug,十分遺憾,若有大哥mm們願繼續完成,我將非常高興。雖如此,擁有了在這個過程中學到的這些東西,我的工作已有足夠的意義。本文的特點是圖文並茂,對錯誤原因解釋詳細,關鍵地方有對linux一些機制的闡述,盡量減少讀者的理解障礙。

代碼包來源:趙炯博士網站http://oldlinux.org/Linux.old中下載bochs安裝文件、linux-0.11.tar.Z源碼包、linux-0.11-devel-040923.zip源碼包(該源碼在gcc1.4下編譯通過,作為對照使用)。

平台搭建:我使用的環境是VirtualBox中安裝ubuntu-11,與win7共享工作文件夾(其中存有linux-0.11源碼),win7中使用editplus和source insight進行源碼的編輯和閱讀。

一、編譯過程

對linux-0.11在高版本gcc下的編譯過程,網上也有一些散碎材料,趙炯博士的論壇裡和《linux內核完全剖析》中也有一部分介紹。本節依據先後順序將編譯過程中每個錯誤的解決方法依次完整地羅列出來。

1、除錯工具:

(1)sourceInsight,源碼閱讀器肯定需要了,否則豈不是找崩潰嗎?

(2)internet,編譯過程網上有不少人完成了,趙炯博士也完成了,對於一些問題可以查到相應資料。

(3)editplus,這是個編輯器了,我用之多年,比較喜歡,其特點就是小但功能全。

2、問題及解決方法

問題1:

第一次make會出現如圖1.1所示的問題。

圖1.1

這是注釋方式問題 ,as86不支持/**/,改為每行前面用!注釋。

問題2:

再次make後出現如圖1.2所示的錯誤。

圖1.2

修改所有makefile文件的編譯器修改一下,將gas,gld改成as和ld,所有AS的選項參數去掉-c(as不用這個選項),gcc的選項參數去掉-fcombine-regs -mstring-insns(這兩個參數現在的gcc不支持了)。

問題3:

接著又出現如圖1.3所示的編譯錯誤。

圖1.3

這是新舊版本gcc對齊的表達方式不同所造成的,.align n n改為 2n便可。

問題4:

接著又出現如圖1.4所示的編譯錯誤。

圖1.4

上面的錯誤只有static declaration of ‘pause’ follows non-static declaration這類是必須修改的,查看main.c和unistd.h發現產生錯誤的原因:

Main.c中有如圖1.5所示的語句:

圖1.5

而unistd.h文件中有圖1.6所示的聲明語句:

圖1.6

Main.c頭部包含了unistd.h,那麼關於fork、pause、sync系統調用的聲明就重復了,不知道為什麼舊版本的gcc可以編譯通過,需要詳查,在main.c中增加這些函數的內聯聲明的原因是linux-0.11的進程0和1共用一個棧,進程0在創建了進程1後只有等待pause的功能,為了避免進程1棧中數據被破壞, 進程0不可使用棧,那麼就不可使用call來調用fork和pause庫函數,而應該用內聯的方法,防止參數傳遞將棧搞亂。

修改這個問題的方法可以利用條件宏的預處理作用來進行。在main.c開始包含#define _IN_MAIN,而unistd.h中的聲明做如圖1.7所示修改即可。

圖1.7

問題5:

Make後又發現如圖1.8所示的錯誤。

圖1.8

這是編譯器對嵌入式匯編已用過的寄存器聲明無效的報錯信息。查看源文件發現問題出現在_set_base宏這裡。

在 include/linux/sched.h中,有如下語句:
188 #define _set_base(addr,base) \
189 __asm__("movw %%dx,%0\n\t" \
190 "rorl $16,%%edx\n\t" \
191 "movb %%dl,%1\n\t" \
192 "movb %%dh,%2" \
193 ::"m" (*((addr)+2)), \
194 "m" (*((addr)+4)), \
195 "m" (*((addr)+7)), \
196 "d" (base) \
197 :"dx") //無效聲明

去掉197行中的:"dx"這項。也即197行變成了:

197 )

然後去掉所有匯編中的類似的地方:String.h,memory.c,buffer.c,super.c(原因是Bitmap.c)。

這是由於as不斷改進,目前自動化程度越來越高,不用人工指定一個變量需要的寄存器了,所以代碼中的 __asm__("ax")需要全部去掉。如bitmap.c和namei.c。

問題6:

Make後又發現如圖1.9所示的錯誤。

圖1.9

查看segment.h 有如圖1.10所示代碼。

圖1.10

將r改為q,該問題就解決了。r表示使用任意動態分配的寄存器,q表示使用動態分配字節可尋址寄存器(eax,ebx,ecx或edx)。

問題7:

Make後又發現如圖1.11所示的錯誤。

圖1.11

這是個左值問題,查看exec.c源碼如圖1.12所示:

圖1.12

這個寫法確實有些別扭,使用get_free_page()申請新頁面,頁面指針pag指向新頁面,申請不到空閒頁面則返回0。如圖1.13修改便可。

圖1.13

類似問題在malloc.c中也有。

問題8:

Make後又發現如圖1.14所示的錯誤。

圖1.14

查看代碼blk.h發現是#elif木有判斷的邏輯表達式,改為#elif 1便可。

問題9:

Make後又發現如圖1.15所示的錯誤。

圖1.15

這個問題不懂怎麼改,按照之間類似問題將第三個冒號後面的寄存器刪掉也不行,求指點。這裡我果斷把所有匯編注釋掉,因為strtok這個函數在內核中沒有被調用。

至此,編譯問題全部解決。

Copyright © Linux教程網 All Rights Reserved