回覆列表
  • 1 # 使用者9599578951863

    (幾年前寫的部落格,貼過來,再更新了些細節)

    可以用gcc編譯個binary,然後用grub呼叫執行。

    首先,為了方便執行和除錯我們需要一個虛擬機器。虛擬機器有很多選擇,這裡用最簡單的qemu。

    先用dd建立一個檔案作為虛擬盤,100MB就可以了:

    然後對這個虛擬磁碟進行分割槽:

    用命令n建立一個分割槽就可以了。通常情況下分割槽的起始扇區是2048。用命令w把變動寫入虛擬盤。

    把這個分割槽虛擬成裝置檔案:

    這裡指定了起始扇區的偏移量。2048個扇區,每個扇區512個位元組,總共是1048576位元組。

    格式化:

    掛載起來,這樣就可以方便地往裡面放kernel和grub需要的配置檔案和模組什麼的:

    安裝grub:

    使用qemu來啟動虛擬機器:

    這時候應該能夠看到grub的提示符了。當然現在還沒有grub選單也沒有kernel,我們暫時先關掉虛擬機器。

    接下來可以為grub建立個multiboot啟動選單:

    製作選單命令:

    確保資料寫回了虛擬盤:

    這時候如果你再開啟虛擬機器,應該就可以看到啟動選單了,當然因為還沒有kernel,選擇選單項後無法繼續,會提示kernel找不到。

    下一步,我們用c語言從頭編寫個最簡單kernel程式。這個kernel沒有實現作業系統的基本功能。但是可以被grub裝載和執行。

    kernel.c:

    有必要再寫個連結模板,確保編譯好的kernel裝載在記憶體地址0x100000,這裡是grub程式碼最後跳轉到的區域,從這裡我們的kernel接過了接力棒。

    kernel.ld:

    還有一個Makefile,主要是設定一些編譯選項。

    Makefile:

    編譯生成kernel並放入我們的虛擬盤裡:

    再次啟動虛擬機器,在啟動選單裡選擇multiboot我們的kernel,應該就能看到Hello World!的字元顯示在虛擬機器螢幕上了。

    如果想要除錯,可以執行gdb。因為我們在啟動qemu的時候使用了-s選項,所以qemu預設會開啟tcp埠1234作為gdb除錯埠。在gdb中可以使用target remote tcp::1234命令來連線。試試看連線,會發現cpu一直在執行0x100066處的指令。用objdump -D kernel看下kernel的彙編程式碼:

    0x100066處的指令正好是死迴圈的那條jmp指令。

    (以上在Arch Linux上透過。使用的grub版本是2.02-beta2。)

  • 中秋節和大豐收的關聯?
  • 我的白色羊毛衫發黃了,如何才能讓它變白啊?