1. 程式人生 > >linux0.11 編譯遇到的問題

linux0.11 編譯遇到的問題

在oldlinux網址下載了linux0.11能夠編譯通過的原始碼,在ubuntu13.10的機子上能夠編譯成功(gcc版本4.8.1),但是在boshs上確無法執行,總結有如下問題:

1. 反覆出現Loading system... 。一步一步除錯,發現當setup完後並沒有進入到head中,通過檢視Image二進位制檔案,發現第5扇區(0xa00)開始處的指令並不是head程式碼。經過一步一步反覆除錯,發現ld程式將main.c中的main函式作為入口地址了(本來應該是head),嘗試將main函式改名為kmain後成功,當然head.s中相應的一個地方也要改。

2. 顯示Loading system ... 後就一直停在這裡。一步一步插樁除錯,發現在main函式中第一次fork然後呼叫copy_process出現問題,首先find_empty_process呼叫成功返回1,然後進入copy_process函式,get_free_page也執行成功,但是接下來將程序0的資料結構複製給程序1的操作失敗了,問題出現在*p=*current賦值語句上,網上各種百度了下,原因在於這條語句彙編後其實就是串操作,串操作開始時,首先要設定方向位DF,但是這裡編譯器認為已經cld過了,又由於這裡方向位在之前某個地方修改過,所以導致串操作方向出錯,解決辦法是在這條語句之前加入如下嵌入彙編程式碼:

__asm__ volatile ("cld");
除了fork.c檔案中需要加入這條語句之外,在super.c中read_super函式裡面的下面語句之前也要加上
*((struct d_super_block *) s) = *((struct d_super_block *) bh->b_data);
還有在inode.c中read_inode函式裡面
*(struct d_inode *)inode =  ((struct d_inode *)bh->b_data) [(inode->i_num-1)%INODES_PER_BLOCK];

出現串操作方向錯誤的原因其實是linux的一個bug,首先在setup_paging函式中linux為了程式碼效率,倒序裝入頁表,導致設定了std方向位,但並未改回。因此可在該函式ret前cld一下。另外一個相同的bug在在核心程式碼的get_free_page函式中,同樣在程式碼最後增加一個cld。這是第二個方法。

3. 上面3處修改過之後,發現當回車插入root軟盤之後反覆出現Reset floppy called的問題。 網上找到一個原因說法以及解決辦法:

原因:mount_root -> read_super -> check_disk_change-> floppy_change-> floppy_on-> ticks_to_floppy_on 會啟動b盤的驅動器,這會導致unexpected_floppy_interrupt被call,然後recalibrate被設為1。當do_fd_request第一次被call用於讀取super block的時候,遇到recalibrate==1 就呼叫recalibrate_floppy。問題來了,current_drive變數還沒有機會被賦值,它應該等於1卻是0。於是導致recalibrate出錯,recal_interrupt設reset=1 -> reset_floppy ->reset_interrupt -> recalibrate_floppy (current_drive依然並且永遠是錯的) ->recal_interrupt->reset_floppy->... 不斷的死迴圈和列印Reset-floppy called。

解決辦法:在recalibrate_floppy中向hardware傳遞正確的driver號能避免這個問題。我直接在recalibrate_floppy函式中對current_drive=1。

另外我使用的是b軟盤作為root根目錄,因此在bootsect.s中ROOT_DEV需修改為0x021d。到此終於能夠將linux0.11跑起來了,但是又有一個問題,第一次能夠執行,關閉後再執行就失敗了,停在如下圖所示的地方:


但是通過從新換個b軟盤(拷貝新的rooimage-0.11)就可以解決,猜想原因是第一次執行對軟盤某個地方進行了修改。

-------------------------------------------------------------

對於上面那個只能執行一次到問題,今天終於解決了。確實有可能第一次執行時,rootimage遭到修改。解決辦法如下:

1. 首先在linux系統上掛載rootimage-0.11映象(ubuntu 12.04):

sudo mount -t minix -o loop rootimage0.11 /mnt/minix

2. cd 進入/mnt/minix目錄,再進入/etc目錄,然後sudo vim rc檔案,將第一行到update &刪除(因為從原始碼main.c可以看到,作業系統掛載根檔案系統後,開啟tty0終端,然後又開啟rc檔案輸出===OK,vi這個rc檔案,發現執行了一個update程式,所以猜想就是這個命令程式導致的問題)。

3. 解除安裝minix:sudo umount /mnt/minix。再次執行問題就解決了。

後面細想可能是update這個程式一直在後臺執行,當關閉bochs後導致rootimage的minix檔案系統出現問題,出現什麼問題還是不得而知。。另外出現問題後無法再次在ubuntu上掛載了。