從零實現一個操作系統-day1

我的博客: startcraft.cn

目的

從這次春招中的碰壁和各種感悟,深刻體會到自己基礎知識的不足,從零實現一個操作系統可以幫助自己更好得了解操作系統的知識。自己很早之前就開始有寫一個微型操作系統的想法,之前也實踐過,但弄了幾天就放棄了,發現自己的毅力太差了,其實就是太懶了,寫blog的目的也有敦促自己,不要懈怠。

資料

感謝前輩們無私提供的各種教程,這系列blog(希望是系列)跟着hurlex-doc教程來學習,當作自己的學習筆記和敦促自己努力不要偷懶


那就開始吧

環境配置

首先是環境的配置,我使用的系統是ubuntu 18.04,然後需要下載一個虛擬機qemu

sudo apt-get install qemu

sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu

腳本文件

教程中用到的各種腳本文件

Makefile

#!Makefile

C_SOURCES = $(shell find . -name "*.c")
C_OBJECTS = $(patsubst %.c, %.o, $(C_SOURCES))
S_SOURCES = $(shell find . -name "*.s")
S_OBJECTS = $(patsubst %.s, %.o, $(S_SOURCES))

CC = gcc
LD = ld
ASM = nasm

C_FLAGS = -c -Wall -m32 -ggdb -gstabs+ -nostdinc -fno-builtin -fno-stack-protector -I include
LD_FLAGS = -T scripts/kernel.ld -m elf_i386 --nostdlib
ASM_FLAGS = -f elf -g -F stabs

all: $(S_OBJECTS) $(C_OBJECTS) link update_image

.c.o:
	@echo 編譯代碼文件 $< ...
	$(CC) $(C_FLAGS) $< -o $@

.s.o:
	@echo 編譯彙編文件 $< ...
	$(ASM) $(ASM_FLAGS) $<

link:
	@echo 鏈接內核文件...
	$(LD) $(LD_FLAGS) $(S_OBJECTS) $(C_OBJECTS) -o time_kernel

.PHONY:clean
clean:
	$(RM) $(S_OBJECTS) $(C_OBJECTS) time_kernel
	.PHONY:update_image
update_image:
	sudo mount floppy.img /mnt/kernel
	sudo cp time_kernel /mnt/kernel/time_kernel
	sleep 1
	sudo umount /mnt/kernel

.PHONY:mount_image
mount_image:
	sudo mount floppy.img /mnt/kernel

.PHONY:umount_image
umount_image:
	sudo umount /mnt/kernel

.PHONY:qemu
qemu:
	qemu -fda floppy.img -boot a

.PHONY:bochs
bochs:
	bochs -f tools/bochsrc.txt

.PHONY:debug
debug:
	qemu -S -s -fda floppy.img -boot a &
	sleep 1
	cgdb -x tools/gdbinit

makefile文件是構建大型工程所必需的,我們來看看這個makefile文件幹了什麼
第1-4行定義了一些變量 這些變量是什麼 首先我們要知道編譯的過程
首先要把源文件編譯成中間代碼文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,這個動作叫做編譯(compile)。然後再把大量的Object File合成執行文件,這個動作叫作鏈接(link)
C_SOURCES和S_SOURCES定義的是C和彙編的源文件,採用shell命令對所有以.c和.s的文件進行查找
C_OBJECTS和S_OBJECTS使用了patsubst將所有的.c和.s的文件名替換爲.o也就是目標文件
後面3行就是定義了一些工具的名稱gcc是c語言的編譯器,ld是鏈接器,nasm是彙編器
再後面三個變量就是編譯連接的一些選項

gcc

  • -c 編譯和彙編但是不鏈接
  • -Wall 編譯後顯示所有警告
  • -m32 以32位模式編譯
  • -ggdb 此選項將儘可能的生成gdb的能夠使用的調試信息
  • -gstabs+ 此選項以stabs格式聲稱調試信息,並且包含僅供gdb使用的額外調試信息.
  • -nostdinc 使編譯器不再系統缺省的頭文檔目錄裏面找頭文檔,一般和-I聯合使用,明確限定頭文檔的位置
  • -fno-builtin 不承認不以__builtin_開頭的函數爲內建(built-in)函數
  • -fno-stack-protector 禁用堆棧保護 不保護堆棧溢出
  • -I include 指定頭文件的搜索目錄

ld

  • -T scripts/kernel.ld 使用指定的鏈接腳本kernel.ld
  • -m elf_i386 生成i386平臺下的elf格式的可執行文件
  • -nostdlib 不連接c語言標準庫

標籤的功能

再往下是目標all,它後面的是這個makefile在缺省條件下的目標,即生成所有的c和彙編的目標文件(.o)
並且完成鏈接和更新鏡像
.c.o表示的是%.o:%.c 即對所有xx.o的目標文件它的依賴是xx.c .s.o同理
$<表示第一個依賴文件 $@表示目標文件

link標籤是將c的目標文件和彙編的目標文件鏈接在一起輸出爲time_kernel文件
update_image標籤顧名思義就是更新鏡像文件,qemu加載的就是操作系統的鏡像,更新過程是先掛載鏡像,然後用time_kernel覆蓋,然後卸載鏡像
clean標籤就是刪除所有生成的文件僅僅保留源代碼
剩下的標籤像 mount_image umount_image就是掛載和卸載鏡像 qemu就是啓動qemu虛擬機
bochs是另一個虛擬機可以忽略 debug就是以debug模式啓動qemu來調試程序

kernel.ld

項目使用的鏈接器的腳本

/*
* kernel.ld -- 針對 kernel 格式所寫的鏈接腳本
*/

ENTRY(start)
SECTIONS
{
	/* 段起始位置 */

	. = 0x100000;
	.text :
	{
		*(.text)
		. = ALIGN(4096);
	}

	.data :
	{
		*(.data)
		*(.rodata)
		. = ALIGN(4096);
	}

	.bss :
	{
		*(.bss)
		. = ALIGN(4096);
	}

	.stab :
	{
		*(.stab)
		. = ALIGN(4096);
	}

	.stabstr :
	{
		*(.stabstr)
		. = ALIGN(4096);
	}

	/DISCARD/ : { *(.comment) *(.eh_frame) }
}

這個腳本暫時看不懂2333,隨着項目繼續進行應該可以看懂吧(大概)
今天也很晚了,先到這吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章