作者:opera 概述 ==== 1)當內核配置了內存盤時, 內核在初始化時可以將軟盤加載到內存盤中作為根盤. 當同時配置了初始化內 存盤(Initail RAM Disk)時, 內核在初始化時可以在安裝主盤之前, 通過引導程序所加載的initrd文件建 立一個內存初始化盤, 首先將它安裝成根文件系統, 然後執行其根目錄下的Linuxrc 文件, 可用於在安裝 主盤之前加載一些內核模塊. 等到linuxrc 程序退出後, 再將主盤安裝成根文件系統, 並將內存初始化盤轉移安裝到其/initrd目錄下. 2)當主盤就是initrd所生成的內存初始化盤時, 不再進行重新安裝, 在DOS下用loadlin加載的搶救盤就是 這種工作方式. 3)引導程序所加載的initrd為文件系統的映象文件, 可以是gzip壓縮的, 也可以是不壓縮的. 能夠識別的文件系統有minix,ext2,romfs三種. 4)當內核的根盤為軟盤時, 內核初始化時會測試軟盤的指定部位是否存在文件系統或壓縮文件映象, 然後 將之加載或解壓到內存盤中作為根盤. 這是單張搶救軟盤的工作方式. 有關代碼 ======== 代碼: ; init/main.c #ifdef CONFIG_BLK_DEV_INITRD kdev_t real_root_dev; 啟動參數所設定的根盤設備 #endif asmlinkage void __init start_kernel(void) { char * command_line; unsigned long mempages; extern char saved_command_line[]; lock_kernel(); printk(linux_banner); setup_arch(&command_line); arch/i386/kernel/setup.c中,初始化initrd_start和initrd_end兩個變量 ... #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && initrd_start < min_low_pfn 0) while (pid != wait(&i)); 等待linuxrc進程退出 if (MAJOR(real_root_dev) != RAMDISK_MAJOR MINOR(real_root_dev) != 0) { ; 如果原來的根盤不是0號內存盤,則使用原來的根文件系統, ; 並且將內存盤轉移到其/initrd目錄下 error = change_root(real_root_dev,"/initrd"); if (error) printk(KERN_ERR "Change root to /initrd: " "error %d\n",error); } } #endif } #ifdef CONFIG_BLK_DEV_INITRD static int do_linuxrc(void * shell) { static char *argv[] = { "linuxrc", NULL, }; close(0);close(1);close(2); setsid(); 設置新的session號 (void) open("/dev/console",O_RDWR,0); (void) dup(0); (void) dup(0); return execve(shell, argv, envp_init); } #endif ; arch/i386/kernel/setup.c #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 #define PARAM ((unsigned char *)empty_zero_page) #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8)) 可用rdev設置的參數 #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) #define INITRD_START (*(unsigned long *) (PARAM+0x218)) 初始化盤映象起始物理地址 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) 初始化盤字節數 void __init setup_arch(char **cmdline_p) { ... #ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; 以塊為單位 rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); #endif ... #ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE