(ubuntu下搜索gnome-disk可以打開磁盤管理)
簡單開機過程 :
①按下電源后,計算機自檢(POST),如果硬件設備(CPU、內存、硬盤、光驅、各種卡)都沒有問題,BIOS會檢查各個硬盤的MBR,看有沒 有可以執行的代碼,如果你把grub安裝到第一個硬盤的MBR上,那BIOS就會找到它,然后把控制權交個這段代碼(其實就是512字節大小的 stage1)。
②stage1根據安裝時提供的信息,如stage2在什么地方,需不需要加載文件系統的對應的stage1_5文件等,找
到stage2文件,並把控制權交給stage2。
③stage2會需要特定位置的grub配置文件grub.cfg文件,如 果找到,就分析其中的內容,形成操作系統選擇菜單(Grub管它叫Menu Interface),如果沒有找到或者這個文件的格式、內容有錯誤,那就顯示grub的命令行提示符。
④當你選擇了菜單中相應的條目,或者輸入了相關的命令,就可以看是引導系統了。比如引導linux的話,stage2會負責將vmlinuz 和initrd(如果有的話)裝載到內存,並把控制權交給vmlinuz。
⑤linux的內核完成對硬件的初始化,並把控制權交給init程序,完成后續的工作了。
grub引導
GRUB 不是 Linux 系統,它本身可以看作一個小型操作系統,內置了簡單的文件系統,可以讀取分區。所以 grub 啟動之后首先就是加載它自己的一個簡單的文件系統,然后讀取自己的相關配置文件。總體上GRUB更像是一個mini os,只不過這個mini os的作用只是加載其他的操作系統,在GRUB中包括stage1、stage1.5(可選)和stage2,其中stage1和stage1.5屬於boot loader,stage2屬於mini os的內核部分。GRUB中stage1過程主要位於MBR的前446字節中(對於支持GPT分區的磁盤,同樣有最開始的512字節作為保護MBR,保護MBR與正常的MBR區別不大,主要是分區表上的不同,在保護MBR中只要一個表示為0xEE的分區,以此來表示這塊硬盤使用GPT分區表,不能識別GPT硬盤的操作系統通常會識別出一個未知類型的分區,並且拒絕對硬盤進行操作),之后的64字節為硬盤的分區表,最后兩個字節為MBR結束標志位(0xAA55)。
grub stage 1
其中stage1要被安裝(也就是寫入)某個硬盤的主引導記錄,或者某個活動分區(這個分區要用fdisk標記成可啟動的)的啟動扇區。 stage1的主要的也是唯一的作用就是找到你存放在硬盤上某個地方的stage2文件,來完成后續的工作。
MBR中前 446個字節,如果把這里面的內容損壞,那么系統會認為當前磁盤沒有啟動引導功能,會嘗試從光盤或者網絡啟動系統
stage1部分占用了446字節,其代碼文件是源碼目錄下stage1/stage1.S文件,匯編后生成一個512字節的boot.img,被寫在硬盤的0面0道1扇區中,作為硬盤的MBR。stage1的工作很簡單,就是加載0面0道2扇區上的512字節到0×8000,然后跳轉到0×8000執行。在0面0道2扇區上的512字節內容為stage1/start.S
文件匯編后生成。該扇區上的內容的作用是加載stage1.5或是stage2過程,並將控制權轉交。
grub stage 1.5
在stage1過程將控制權轉交后,接下來就是GRUB的核心過程了。該過程之所以區分stage1.5和stage2,主要原因是GRUB和GRUB2的區別。在GRUB2中,將stage1.5過程集成到了stage2的過程中,所以stage1.5過程僅僅是針對GRUB的。下面將介紹GRUB。
Stage1.5過程很無辜,它的作用很單一,但是非常關鍵。它的主要功用就是構造一個boot分區系統對應的文件系統,這樣可以通過文件系統的路徑(/boot/grub/)尋找stage2過程需要的core.img,進而加載到內存中開始執行。
Stage1.5存在於0面0道3扇區開始的地方,並一直延續十幾k字節的區域,具體的大小與相應的文件系統的大小有關(文中涉及到了0面0道1-3+x扇區,這部分扇區為保留扇區,BIOS不會放置任何數據。正因為如此如果轉換到GPT分區形式,系統將不能被正確引導,MBR后面的扇區都被其他內容所占據)。Stage1.5過程被構建成多種不同類型,但是功能類似,下面簡單介紹一下基本的stage1.5過程的文件系統。e2fs_stage1_5(針對ext2fs,可引導ext2和ext3文件系統)、fat_stage1_5(針對fat文件系統,可引導fat32和fat16)、ffs_stage1_5、jfs_stage1_5、minix_stage1_5、reiserfs_stage1_5、vstafs_stage1_5和xfs_stage1_5,這些文件被稱為stage1.5過程,這些文件每個至少都在11k以上。除此之外還有兩個比較特殊的文件,分別為nbgrub和pxegrub,這兩個文件主要是在網絡引導時使用,只是格式不同而已,他們很類似與stage2,只是需要建立網絡來獲取配置文件。
對於ext2fs文件系統,用於生成該文件系統的stage1.5過程文件(e2fs_stage1_5)的代碼為stage2/fsys_ext2fs.c
文件。
在stage2/filesys.h
文件中定義了每個文件系統對外的接口,用於上層調用,作為stage2過程尋找核心代碼使用,文件系統一般被定義的接口主要就是三個函數,分別是mount、read和dir函數。對應ext2fs,其定義的函數為:
1 #ifdef FSYS_EXT2FS 2 #define FSYS_EXT2FS_NUM 1 3 int ext2fs_mount (void); 4 int ext2fs_read (char *buf, int len); 5 int ext2fs_dir (char *dirname); 6 #else 7 #define FSYS_EXT2FS_NUM 0 8 #endi
https://blog.csdn.net/langeldep/article/details/8788119
針對ext2fs有如上的函數名稱,每個函數將具體在stage2/fsys_ext2fs.c
文件中被定義,這里面沒有包含任何的寫的過程,對於bootloader而言僅僅讀就可以完成任務了,沒必要對其系統進行寫操作。其中ext2fs_mount函數用於檢查文件系統類型,並將superblock讀入到內存中;ext2fs_read函數和ext2fs_dir函數用於對文件系統具體的操作。在stage2/fsys_ext2fs.c
文件中除了需要對這三個函數的定義之外,還需要文件系統的屬性的數據結構(superblock、inode和group結構,這些結構最初被定義在include/linux/ext2_fs.h
文件中),通過這些數據結構描述一個文件系統。
如果讀者有興趣可以試着創建新的文件系統的支持,可以參照目前存在的一些文件系統的模板(實例)編寫。
grub stage 2
GRUB中的核心過程也就是stage2過程了,該過程主要是在文件系統建立以后選擇合適的操作系統進行加載並轉交控制權,達到最后引導操作系統的目標。由於GRUB屬於multi boot loader,因此在引導的時候要進行選擇,選擇哪種操作系統來運行。在GRUB內部主要包括兩種方式,首先是從grub. cfg中讀取顯示到屏幕讓用戶選擇,其次是通過grub-shell中定義的命令手動進行啟動。本文將在后面介紹這兩種方式如何運行,接下來先介紹一下stage2的具體的執行過程。
在上面一節中介紹過,stage1.5過程中將boot分區的文件系統加載了,之后又做了一件事情,就是將控制權轉交給stage2,而stage2入口的地方就是stage2/asm.S
文件。Stage2/asm.S
文件屬於匯編代碼,主要作用是初始化C語言的運行環境,為下面執行C語言的函數做好准備,在准備好之后,將執行init_bios_info(stage2/common.c
)函數。init_bios_info函數的作用是執行一些底層的函數,然后跳轉到cmain執行,cmain函數位於stage2/stage2.c
文件中。cmain函數內部進行一個死循環,在循環內部首先加載配置文件,顯示給用戶,在這同時循環一個內層循環,在內層循環中,獲取配置文件中的命令,並解析執行。過程中如果沒有可用的配置文件,那么進入命令行模式(enter_cmdline函數),如果找到可用的menu,那么開始執行menu的對應的內容(run_menu函數)。對於enter_cmdline(stage2/stage2.c
)函數,將調用find_command(stage2/cmdline.c
),進而執行相應命令的函數。對於run_menu(stage2/stage2.c
)函數,將調用stage2/cmdline.c
文件中的run_script函數,進而調用find_command,執行相應命令的函數。
這兩種方式雖然經過了不同的過程,對用戶輸入的行為進行分析和處理,最終調用的函數為find_command,在該函數中順序循環比較“輸入”的命令是否與系統內部定義的相同,如果相同轉到執行該函數。在這個比較的過程中包含了一個全局的數據結構為struct builtin(stage2/shared.h
),由該數據結構組成了一個table類型(stage2/builtins.c
),將命令與相對應的builtin結構對應一起並進行串聯。下面描述一下builtin結構的定義:
1 struct builtin { 2 /* 命令名稱,重要,是搜索命令時的依據*/ 3 char *name; 4 /* 命令函數,重要,是搜索匹配后調用的函數*/ 5 int (*func) (char *, int); 6 /* 功能標示,一般未用到. */ 7 int flags; 8 /* 簡短幫助信息*/ 9 char *short_doc; 10 /* 完整幫助信息*/ 11 char *long_doc; 12 }; 13 struct builtin *builtin_table[];
有興趣的讀者可以對上面的內容進行擴展,形成自己的命令,主要在stage2/builtins.c
文件中按照預定的格式更新,並添加到builtin_table中即可。
在上面打開配置文件的過程中,主要是通過一些文件操作函數(被定義在stage2/disk_io.c
中)完成。這些文件操作函數主要包括:grub_open、grub_read、grub_seek和grub_close等,這些函數屬於grub對外的上層接口,具體的函數內部將調用前文中提到的boot分區對應的文件系統的相應的函數完成,這個過程主要是通過回調函數來完成。該過程整體思路類似於面向對象過程,通過對象操作具體的函數。
只要看到內核的啟動菜單,表示已經成功的進入了grub的stage 2階段,因為啟動菜單是在2 stage生成的.
“因為stage1的容量有限(主引導記錄MBR和啟動扇區的大小只能夠是512字節),所以它對文件系統是無法識別的,那如果你把 stage2存放在ext2或者fat格式的文件系統上,它如何來找到這個文件呢?這就要用到上面提到的那些stage1_5的文件了,它們負責解釋文件 系統。你的stage2放在什么格式的文件系統上,就要調用對應的那個stage1_5文件。比如,你把stage2存放在ext2格式的文件系統上,就 需要e2fs_stage1_5;stage2存放在fat格式的文件系統上,就需要fat_stage1_5了
grub的話,肯定是要在mbr里寫東西的,但446字節的機器碼也干不了太多東西,只是負責把后續的內容加載到內存在執行而已。這個寫到mbr的是stage1,它加載的是寫在mbr之后62個扇區中的stage1.5(因為過去磁盤是按磁道還划分分區的,一個碰道63個扇區,因為mbr占據了第一個磁道的第一個扇區,所以第一個分區只能從第二個磁道開始,這樣在mbr和第一個分區之間就留下了62個扇區的空間,62*512byte=31KB)。mbr之前說了容量太小沒法放下識別文件系統的代碼,只能以計算扇區絕對偏移的方法加載stage1.5,但31KB的stage1.5就足夠了(但基本也只夠一種類型的文件系統,所以stage1.5是有好幾個,分別對應ext4,xfs等等,在grub安裝時根據需要寫入,隨便一提,正是因為GPT分區表占用了后62個扇區的相當一部分位置,導致空間不夠寫下stage1.5,所以需要額外分出一個非常小的分區來存放)。stage1.5可以識別文件系統,然后根據安裝時硬寫到里面的系統路徑(hexdump可以看到)找到stage2,然后這個stage2才是真正負責干活的,它會讀取grub.cfg並生成啟動菜單,然后根據你的選擇加載內核並把執行權限轉過去,完成啟動。”--------------------------來自知乎
grub命令
1.grub-install /dev/sda 修復grub1 1.5 2 所有階段的數據 修復的時候不依賴於任何外部配置文件
2.grub中對應的/根分區不是操作系統的根分區,它代表的是/boot分區
3.(hd0,0) 表示第一塊磁盤的第一個分區 即代表sda1
4.(hd0) 表示第一塊磁盤 即表示sda
5.grub這個命令依賴於/boot/grub目錄下的一些配置文件,如果這些文件被刪除或者移動,那么使用grub命令無法正常修復
6.如果沒有使用grub修復過系統,那么/boot/grub/目錄下的文件只有兩個文件影響系統啟動(grub.conf 和 splash.xpm.gz)
如果使用過grub修復過系統,那么 /boot/grub 目錄下的其它配置文件同樣會影響到系統啟動。