PXE

96
金波_xu
2018.10.20 14:12* 字数 1875

Linux的启动过程:

这里先给一个简单的概述,后面再是详述:
a. 位于ROM的BIOS首先加电自检,然后装载MBR内容到RAM,将控制权交给RAM中的bootloader(比如GRUB);
b. bootloader进行自身的多阶段引导,装载一些文件系统的驱动等,最后将内核装载入RAM;
c. 内核首先运行,然后挂载内存文件系统initrd;
d. initrd针对当前的硬件情况,决定应加载哪些内核模块并加载之,并且挂载root filesystem(系统盘),最后用/sbin/init来代替自己的/init以起到启动1号进程init的作用;
e. init进程工作,启动系统服务,处理用户登录事宜,最终Linux系统可用。

#

1.BIOS引导

BIOS是位于ROM中的,所以可以说就是机器本身。相反地,磁盘就不一定算机器本身的了,因为可以远程挂载。

a. 首先,BIOS加电自检,即所谓的POST(Power On Self Test)
b. 然后,按照BIOS中设置的引导顺序(如:硬盘分区、光驱、软盘、USB设备等)读入引导块。 一般来说,从硬盘启动,引导块指的就是MBR(Master Boot Record,主引导记录)。MBR是一个 512 字节大小的扇区,位于磁盘的第一个扇区(0道 0柱面 1扇区),它在硬盘上的三维地址为(柱面,磁头,扇区)= (0,0,1)
c. 当 MBR 被加载到 RAM 中之后,BIOS就将控制权交给MBR了,而MBR中的内容可以是GRUB或LILO.

2. GRUB引导

MBR是一个512字节的区域,其中放置的是bootloader程序。bootloader是引导程序,它一般分为多阶段引导(见下面对GRUB的介绍)。常见的bootloader程序有GRUB和LILO.

GRUB(GRand Unified Bootloader),遵循FSF(Free Software Foundation)的多引导规范(Multiboot Specification),它允许用户选择一种操作系统来启动。

GRUB分为version 1和version2,前者已经是legacy了,后者才是常用的。

GRUB的引导分为3个stage:

  • Stage 1: boot.img刚好是446个字节,位于MBR中; 首先,boot.img被装载到RAM中,然后它会去装载core.img;

  • Stage 1.5: core.img位于MBR和第一个partition之间的空的sectors里面; core.img会加载一些模块以及文件系统的驱动,然后它会进入Stage 2.

  • Stage 2: /boot/grub 位于硬盘分区上 在这个阶段,用户可以选择一个操作系统进行启动(boot)了

在 /boot/grub/grub.conf 文件中,存放的就是关于这些供用户选择的操作系统的信息。对于Linux操作系统来说,这个文件会指明kernel,即vmlinuz文件存放于何处,以及 initrd 存放于何处,等等。

在选择了一个操作系统之后,就进入了内核引导阶段。

3. 内核引导

bootloader负责装载kernel image(vmlinuz)和initrd image(initramdisk)到内存中。在bootloader把控制权交给Kernel之前,vmlinuz和initrd就已经被装载在内存中了。

  • Kernel(vmlinuz)首先运行起来,直到它能够mount这个initrd所代表的ramdisk,就好像mount了一个文件系统。

  • initrd的作用是什么呢? 因为硬件有各种各样,kernel需要怎样的模块/驱动就是不一样的,initrd会决定哪些内核模块是需要被加载以支持当前的硬件,并且会加载这些内核模块,并且保证最终root filesystem会被mount起来。 所以,其实initrd就是一个非常小的操作系统镜像。它唯一的目的就是为真正的操作系统的启动做准备。比如,它会mount真实的root filesystem(系统盘) – 必须包含基本的二进制目录(/bin 和 /sbin),库(/lib 和 /lib64), 以及配置文件目录 (/etc). 最终,/init (详见参考文献) 会使用实际操作系统的 /sbin/init 来代替它自己,也就是使之成为init进程(1号进程)。至此,内核引导结束。

#

initrd.img和vmlinux的作用

译安装完内核后在/boot下没有initrd.img

vmlinuz自然就是内核了,initrd.img是一个小的映象,包含一个最小的linux系统。通常的步骤是先启动内核,然后内核挂载initrd.img,并执行里面的脚本来进一步挂载各种各样的模块,然后发现真正的root分区,挂载并执行/sbin/init… …。 initrd.img当然是可选的了,如果没有initrd.img,内核就试图直接挂载root分区。 之所以要有initrd,那是为了启动的时候有更大的灵活性。比如,你把ext3支持编译成模块了。偏偏你的root分区又是ext3的。这下就麻烦了。因为内核需要挂载root分区之后才能加载ext3支持。但是没有ext3支持就没法挂载root分区。initrd就是用来解决这个问题的。 类似的用这个东西还可以做其他的事情,比如从usb盘启动linux也会面临上面类似的问题。用initrd就能搞定了。 甚至,我想在有些嵌入式设备里面都不需要真正的root分区,用initrd就足够搞定一切了。

主要是为了解决vmlinuz太大的问题,用initrd可以解决这个问题。否则的话在2.6的内核中启动会失败的。

PXE启动原理以及与普通Linux启动的对比

参考文献:https://blog.csdn.net/nirendao/article/details/76012939

  1. 内核引导之前的不同:普通的从硬盘启动Linux系统最初是BIOS将MBR加载入内存,然后将控制权交给MBR中的bootloader程序(如GRUB),bootloader程序经过几个stage的加载后,最后将vmlinuz加载入内存,开始内核引导;而PXE的启动过程在内核引导之前,是由BIOS中的PXE固件开启NBP程序(比如DHCP的网络通信),然后下载vmlinuz和initrd,之后再进入内核启动过程。
  1. 内核引导之后的不同:vmlinuz和initrd运行得差不多了之后,普通的硬盘Linux启动就从本地硬盘加载/sbin/init并运行为1号进程,以及启动系统服务等等,而PXE的启动在内核引导完成之后,仍然会通过网络的方式(但不是TFTP协议,而是其他更加健壮的协议如NFS、iSCSI等),加载真正的完整操作系统,如/sbin/init应该就是位于网络远端的硬盘上。

以iSCSI为例,网络远端的硬盘以iSCSI协议挂载到了当前机器,就好像是本地磁盘一样。这就是PXE+iSCSI的启动方式了。

PXE服务器部署细节

  1. dhcp配置文件
subnet 192.168.181.0 netmask 255.255.255.0 {
option routers 192.168.181.129;
option subnet-mask 255.255.255.0;
range 192.168.181.50 192.168.181.60;
next-server 192.168.181.129;      #指定pxe.tftp服务器的位置
filename "pxelinux.0";            #pxelinux.0是一个bootloader,类似于grub,通过它来load kernel
}
  1. tftp配置
#mkdir /tftpboot && cd /tftpboot
#cp /mnt/isolinux/* /tftpboot  #为了简单就全copy了
#mkdir pxelinux.cfg
#cp /mnt/isolinux/isolinux.cfg ./default
default

3.ftp配置略

编辑多系统启动菜单

[root@tianyun tftpboot]# vim pxelinux.cfg/default
label centos6u8
menu label ^Install centos 6
menu default
kernel centos6u8/vmlinuz
append initrd=centos6u8/initrd.img

label centos7u3
menu label ^Install centos 7
kernel centos7u3/vmlinuz
append initrd=centos7u3/initrd.img inst.stage2=ftp://192.168.2.128/centos7u3
inst.repo=ftp://192.168.2.128/centos7u3

label rescue
menu label ^Install centos 7
kernel centos7u3/vmlinuz
append initrd=centos7u3/initrd.img rescue inst.stage2=ftp://192.168.2.128/centos7u3
inst.repo=ftp://192.168.2.128/centos7u3

label local
menu label ^Boot from local drive
localboot 0xffff


[root@tianyun ~]# cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

mount -o loop /CentOS-6.8-x86_64-bin-DVD1.iso /var/ftp/centos6u8
mount /var/CentOS-7-x86_64-DVD-1611.iso /var/ftp/centos7u3/


[root@tianyun ~]# chmod +x /etc/rc.d/rc.local
自动化运维