RamDisk (Initrd)小结

RamDisk(Initrd)小结:html


名称:
  initrd -- boot loader initialized RAM disk,就是由启动加载器进行初始化的RAM DISK;
描述
   /dev/initrd这个特殊文件是一个只读的块设备文件。/dev/initrd设备文件是一个在内核被启动以前由启动加载器进行初始化的RAM disk。

   随后,内核利用/dev/initrd设备文件的内容进行两个阶段的(系统)自举。

   boot loader 会将存储介质中的内核文件及 initrd文件(initrd会解压缩后再释放)加载到内存,而后内核进行初始化,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd 文件系统。

   在(系统)自举的第一个阶段,挂载/dev/initrd中精简的根文件系统。这个根文件系统包含必备的liunx目录和程序,甚至也有一个init脚本(或程序linuxrc;在RedHat5中是init),必需的一些驱动模块;而后执行init脚本,完成加载驱动及模块的任务;脚本执行后期,会借助刚才加载的驱动及模块挂载上真正的根文件系统,而且切换根文件系统从精简的initrd根文件系统到根文件系统;
node


  在第二个阶段,根文件系统已经被挂载,系统会运行真正根文件系统中的/sbin/init继续完成系统其它的初始化工做;

  (在桌面或服务器 Linux 系统中,initrd 是一个临时的文件系统。其生存周期很短,只会用做到真实文件系统的一个桥梁。在不少没有存储设备的嵌入式系统中,initrd 是永久的根文件系统;)
   
 补充:
  在真正的运行环境中,对内核需求是短小而精悍,不该该静态包含进太多驱动模块;因此其采用模块化设计,大部分设备模块是在须要使用时才加载相应驱动的。可是Linux内核启动最后一步,须要挂载根文件系统,而后运行/sbin/init建立init内核线程来引导初始化系统。而根文件系统可能在硬盘、磁盘阵列、nfs、flash上,同时根文件系统的格式也是五花八门。此时,要是实在不想包含这么多驱动到内核的话,可使用initrd做为一个过渡。另外,内核在编译的时候,是能够选择是否支持initrd,若是使用initrd,则系统自居是两段式的。若是不使用initrd,须要编译进去各类驱动(没作过相关实验,不发表看法:网上编译内核教程一堆堆的,可是貌似不少问题,你要感受那是理所固然的...就引导了o(╯□╰)o);而且若是换新的文件系统,可是刚好内核又没有更换,这是胡恐怕只有从新编译内核了而不是仅仅的只mkinitrd就完事大吉了。
linux


下面是2.6内核对模块选择路径:
Linux Kernel Configuration
  -> Device Drivers
   ->Block devices
    ->RAM block device support
     ->Default number of RAM disks  (设定Ramdisk的个数,默认是16)
     ->Default RAM disk size (kbytes) (设定Ramdisk的大小,默认4096k)
Linux Kernel Configuration
  ->General setup
   ->Inital RAM filesystem and RAM disk(initramfs/initrd) support
 
服务器

  若是对Ramdisk的支持已经编译进内核,咱们就可使用它了,固然对于我RedHat5.4来讲默认是使用该项的;

RamDisk文件系统中脚本init做用:
    init文件是RamDisk的核心文件,其中的其余文件都是为该脚本服务的;临时Mount虚拟root,并自动运行该文件系统中的init脚本 文件 ,这个文件将实际加载真实物理root所须要的设备驱动模块(如raid或scsi驱动),和文件系统驱动模块,全部必需的驱动调入后,这个脚本将物理root Mount上,并卸下Ramdisk虚拟根文件系统,此时根文件系统就已经为真实根文件系统了,而后系统进入正常引导,加载各service ,启动应用程序;
app


init脚本的格式:
ide

  
  
  
  
  1. #!/bin/nash 
  2. mount -t proc /proc /proc 
  3. setquiet 
  4. echo Mounting proc filesystem 
  5. echo Mounting sysfs filesystem 
  6. mount -t sysfs /sys /sys 
  7. echo Creating /dev 
  8. mount -o mode=0755 -t tmpfs /dev /dev 
  9. mkdir /dev/pts 
  10. mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts 
  11. mkdir /dev/shm 
  12. mkdir /dev/mapper 
  13. echo Creating initial device nodes 
  14. mknod /dev/null c 1 3 
  15. mknod /dev/zero c 1 5 
  16. mknod /dev/systty c 4 0 
  17. mknod /dev/tty c 5 0 
  18. mknod /dev/console c 5 1 
  19. mknod /dev/ptmx c 5 2 
  20. mknod /dev/rtc c 10 135 
  21. mknod /dev/tty0 c 4 0 
  22. mknod /dev/tty1 c 4 1 
  23. mknod /dev/tty2 c 4 2 
  24. mknod /dev/tty3 c 4 3 
  25. mknod /dev/tty4 c 4 4 
  26. mknod /dev/tty5 c 4 5 
  27. mknod /dev/tty6 c 4 6 
  28. mknod /dev/tty7 c 4 7 
  29. mknod /dev/tty8 c 4 8 
  30. mknod /dev/tty9 c 4 9 
  31. mknod /dev/tty10 c 4 10 
  32. mknod /dev/tty11 c 4 11 
  33. mknod /dev/tty12 c 4 12 
  34. mknod /dev/ttyS0 c 4 64 
  35. mknod /dev/ttyS1 c 4 65 
  36. mknod /dev/ttyS2 c 4 66 
  37. mknod /dev/ttyS3 c 4 67 
  38. echo Setting up hotplug. 
  39. hotplug 
  40. echo Creating block device nodes. 
  41. mkblkdevs 
  42. echo "Loading uhci-hcd.ko module" 
  43. insmod /lib/uhci-hcd.ko  
  44. echo "Loading ohci-hcd.ko module" 
  45. insmod /lib/ohci-hcd.ko  
  46. echo "Loading ehci-hcd.ko module" 
  47. insmod /lib/ehci-hcd.ko  
  48. mount -t usbfs /proc/bus/usb /proc/bus/usb 
  49. echo "Loading jbd.ko module" 
  50. insmod /lib/jbd.ko  
  51. echo "Loading ext3.ko module" 
  52. insmod /lib/ext3.ko  
  53. echo "Loading scsi_mod.ko module" 
  54. insmod /lib/scsi_mod.ko  
  55. echo "Loading sd_mod.ko module" 
  56. insmod /lib/sd_mod.ko  
  57. echo "Loading scsi_transport_spi.ko module" 
  58. insmod /lib/scsi_transport_spi.ko  
  59. echo "Loading mptbase.ko module" 
  60. insmod /lib/mptbase.ko  
  61. echo "Loading mptscsih.ko module" 
  62. insmod /lib/mptscsih.ko  
  63. echo "Loading mptspi.ko module" 
  64. insmod /lib/mptspi.ko  
  65. echo "Loading dm-mod.ko module" 
  66. insmod /lib/dm-mod.ko  
  67. echo "Loading dm-mirror.ko module" 
  68. insmod /lib/dm-mirror.ko  
  69. echo "Loading dm-zero.ko module" 
  70. insmod /lib/dm-zero.ko  
  71. echo "Loading dm-snapshot.ko module" 
  72. insmod /lib/dm-snapshot.ko  
  73. echo Waiting for driver initialization. 
  74. stabilized --hash --interval 250 /proc/scsi/scsi 
  75. echo Making device-mapper control node 
  76. mkdmnod 
  77. mkblkdevs 
  78. echo Scanning logical volumes 
  79. lvm vgscan --ignorelockingfailure 
  80. echo Activating logical volumes 
  81. lvm vgchange -ay --ignorelockingfailure   VolGroup00 
  82. resume /dev/VolGroup00/LogVol01 
  83. echo Creating root device. 
  84. mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00 
  85. echo Mounting root filesystem. 
  86. mount /sysroot 
  87. echo Setting up other filesystems. 
  88. setuproot 
  89. echo Switching to new root and running init. 
  90. switchroot 
  91.  


  脚本执行过程分析:
  第一行#!/bin/nash是一个redhat本身的微型解释器。只包含精简的命令,能作基本的mount、insmod、mkdev等,主要是为了减少iitrd体积;
   
  mount命令挂载上了initrd释放出来的各类内核文件系统/proc、/sys、/dev到相应的位置;

  mknod生成各类设备节点;hotplug开始监听系统总线热插拔的磁盘等uevent事件。mkblkdevs将这些热插拔的磁盘节点建立到/dev下。

  接着insmod开始安装usb,block设备,scsi设备,ide设备,device-mapper的设备驱动,随后系统总线就会收到这些事件,mkblkdevs又会把他们的节点建立到/dev下。咱们的硬盘多数是在这个阶段被找到并建立了相应的设备节点。而后是加载启动逻辑卷管理,使咱们的设备能使用逻辑卷名称。这一步能够不要的

    而后是加载启动逻辑卷管理,使咱们的设备能使用逻辑卷名称;(该步骤非必要)

  (重要)下面mkrootdev:该命令能够建立根文件系统的设备节点;查找内核参数当中的“root=”项;而后解析mkrootdev后面的-t 和-o参数,若是-t是nfs,并且,-o中包含dhcp,那么root的相关信息从dhcp主机取得,若是-o选项不包含dhcp或者-t不是nfs, 则从root=内核参数取真正root文件系统的位置,若是没有root=参数,使用mkrootdev后面的设备做为root设备。若是是-t nfs那么直接添加入口到/etc/fstab文件,包括-t的文件系统类型和-o的选项。若是-t指定的文件系统不是nfs,那么它建立名称为/dev/root的节点,它的Major,Minor设备号使用root=参数的设备号(若是有),或mkrootdev后面的设备的设备号。;它不只可以根据root=/dev/xxx来生成对应的设备节点,还可以在碰到root=LABEL=/ 的状况下探测全部的硬盘分区,以便找到对应着卷标为/的分区。

  因此,mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00这行,会将一条入口信息写入内存中的/etc/fstab,如: /dev/root /sysroot ext3 defaults,ro 0 0 ;注意此时设备是/dev/root.而不是/dev/VolGroup00/LogVol00,但他们的设备号是同样的。 
 
  紧接着后面的mount  /sysroot;就会读取/etc/fstab并加载刚刚mkrootdev写入的这条入口信息所指定的设备,这就是加载/dev/root 到/sysroot下。这时咱们的真正的root才被加载到了系统中。nash在mount时,若是只有一个参数,以它做为root加载点,且它必须是 /sysroot(会同fstab中的作比较)。若是有加载点和设备参数,-t -o必须也被提供,mount丢弃/etc/fstab中的入口的内容,而使用参数提供的信息加载root设备。若如本例,至此/sysroot下是真正物理系统的root分区。/是initrd的内存盘。 
 
  setuproot 并不接受任何参数,而以上面的/sysroot做为咱们的root。安装全部的子分区到/sysroot下。也就是创建咱们的根文件系统树,若是咱们的root 不是由单个分区组成的话。这些信息从/sysroot/etc/fstab.sys中读取。若是它不存在,就从initrd的/etc /fstab.sys中读取。若是仍然不存在,就创建默认的文件系统树: 
 
  挂载(Bind挂载方式)/proc 到/sysroot/proc ,/sys到/sysroot/sys 
 
  最后switchroot卸载/dev,/proc,/sys文件系统,挂载(移动挂载方式)/sysroot到/下面.,而后卸载initrd的/。打开 /dev/console到描述符3,将stdin,stdout,stderr所有定向到3(console),分析内核参数,寻找init=,若是有,以它做为init程序执行,不然,执行默认:搜寻第一个找到的/sbin/init;/etc/init;/bin/init;/bin/sh执行,这就 是全部进程的父进程0 
 
模块化

文章参考:ui

关于Linux-gate.so.1的含义: http://www.linuxidc.com/Linux/2007-07/6221.htm spa

Linux boot process (initrd part): http://bbs.kylin-linux.com/htm_data/9/1003/209.html
http://www.mike.org.cn/articles/linux-xiangjie-linux-initrd/
拓展参考: http://www.ibm.com/developerworks/cn/linux/l-initrd.html(IBM上面用busybox实现了一个精简的initrd)线程

 整理过程,不免出错,但愿共同探讨;

相关文章
相关标签/搜索