本文只是为了演示Linux系统启动过程所必要的元素,并非真正意义上的功能完备的Linux系统。
我的环境是VMware虚拟机,CentOS-6.7-x86_64操作系统。
首先为虚拟机添加一块磁盘,我这里使用默认20G,其实不需要这么大,不过虚拟机嘛,你不选立即分配,它也不会真的占那么大空间。
首先对它进行分区,使用MBR分区表。规划三个分区,一个boot分区200M,一个swap分区2G,剩余空间都给根分区。
[[email protected] ~]# parted -s /dev/sdb mklabel msdos [[email protected] ~]# parted -s /dev/sdb mkpart primary 2048s 200M [[email protected] ~]# parted -s /dev/sdb mkpart primary 200M 2200M [[email protected] ~]# parted -s /dev/sdb mkpart primary 2200M 100% [[email protected] ~]# partx -a /dev/sdb [[email protected] ~]# mkfs.ext4 /dev/sdb1 [[email protected] ~]# mkswap /dev/sdb2 [[email protected] ~]# mkfs.ext4 /dev/sdb3 [[email protected] ~]# parted -s /dev/sdb print Model: VMware, VMware Virtual S (scsi) Disk /dev/sdb: 21.5GB Sector size (logical/physical): 512B/512B Partition Table: msdos Number Start End Size Type File system Flags 1 1049kB 200MB 199MB primary ext4 2 200MB 2200MB 2000MB primary linux-swap(v1) 3 2200MB 21.5GB 19.3GB primary ext4
在/mnt目录下建立目录作为最简化系统的根,将规划作为根分区/dev/sdb3的挂载至该目录。
[[email protected] mnt]# mkdir sysroot [[email protected] mnt]# mount /dev/sdb3 /mnt/sysroot/
在/mnt/sysroot目录下建立FHS目录结构
[[email protected] ~]# cd /mnt/sysroot/ [[email protected] sysroot]# for d in $(ls /); do mkdir -v $d; done mkdir: created directory `bin‘ mkdir: created directory `boot‘ mkdir: created directory `dev‘ mkdir: created directory `etc‘ mkdir: created directory `home‘ mkdir: created directory `lib‘ mkdir: created directory `lib64‘ mkdir: cannot create directory `lost+found‘: File exists mkdir: created directory `media‘ mkdir: created directory `misc‘ mkdir: created directory `mnt‘ mkdir: created directory `net‘ mkdir: created directory `opt‘ mkdir: created directory `proc‘ mkdir: created directory `root‘ mkdir: created directory `sbin‘ mkdir: created directory `selinux‘ mkdir: created directory `srv‘ mkdir: created directory `sys‘ mkdir: created directory `tmp‘ mkdir: created directory `usr‘ mkdir: created directory `var‘
将boot分区/dev/sdb1挂载至/mnt/sysroot/boot
[[email protected] sysroot]# mount /dev/sdb1 /mnt/sysroot/boot [[email protected] sysroot]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/vg0-root 20G 301M 19G 2% / tmpfs 491M 0 491M 0% /dev/shm /dev/sda1 190M 36M 145M 20% /boot /dev/mapper/vg0-usr 9.8G 2.0G 7.4G 21% /usr /dev/mapper/vg0-var 20G 136M 19G 1% /var /dev/sdb3 18G 45M 17G 1% /mnt/sysroot /dev/sdb1 180M 1.6M 169M 1% /mnt/sysroot/boot
在sdb上安装grub,可以看到Grub将grub目录安装到了/mnt/sysroot/boot目录下了。其实还有部分代码是直接写入了磁盘的物理扇区上,比如stage1是直接写入了MBR的前446字节,而根据boot分区的文件类型不同,会将相应的stage1_5代码也写入磁盘的物理扇区靠前的位置,这里应该写的是e2fs_stage1_5。
[[email protected] sysroot]# grub-install --root-directory=/mnt/sysroot/ /dev/sdb Probing devices to guess BIOS drives. This may take a long time. Installation finished. No error reported. This is the contents of the device map /mnt/sysroot//boot/grub/device.map. Check if this is correct or not. If any of the lines is incorrect, fix it and re-run the script `grub-install‘. (fd0)/dev/fd0 (hd0)/dev/sda (hd1)/dev/sdb [[email protected] ~]# ls /mnt/sysroot/boot/grub/ device.map ffs_stage1_5 minix_stage1_5 stage2 xfs_stage1_5 e2fs_stage1_5 iso9660_stage1_5 reiserfs_stage1_5 ufs2_stage1_5 fat_stage1_5 jfs_stage1_5 stage1 vstafs_stage1_5
直接使用CentOS-6的内核和伪根文件系统,不搞那么复杂了,版本号都不要了。
[[email protected] boot]# cd /mnt/sysroot/boot [[email protected] boot]# cp /boot/vmlinuz-2.6.32-573.el6.x86_64 ./vmlinuz [[email protected] boot]# cp /boot/initramfs-2.6.32-573.el6.x86_64.img ./initramfs [[email protected] boot]# ls grub initramfs lost+found vmlinuz
内核启动完成后,还需要启动系统初始化程序,不过真的完成整个系统初始化过程,需要很多其他程序协作,太过复杂。其实也可以随便指定一个别的程序,这里我们为了简化,直接启动一个bash,所以需要把bash移植过去。
[[email protected] ~]# which bash /bin/bash [[email protected] ~]# cp /bin/bash /mnt/sysroot/bin/
仅是这样还不够,bash是运行不起来的,它还依赖一些库文件,因此这些库文件也需要移植。
[[email protected] ~]# ldd /bin/bash linux-vdso.so.1 => (0x00007ffe8fbba000) libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003e81000000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003e76c00000) libc.so.6 => /lib64/libc.so.6 (0x0000003e77000000) /lib64/ld-linux-x86-64.so.2 (0x0000003e76800000) [[email protected] ~]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/ [[email protected] ~]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/
现在还缺一个grub的配置文件,可以自己动手一个。因为我们是准备把这块硬盘拆下来,挂到另一个新建的虚拟机上,所以那个新建的虚拟机只有这一块盘,(hd0,0)和/dev/sda3就是这么来的。另外CentOS启动时默认就会加载SELinux,而这个简化的系统什么都没有,所以它会影响启动,要把它关掉。
[[email protected] ~]# cat /mnt/sysroot/boot/grub/grub.conf default 0 timeout 5 title MiniLinux root (hd0,0) kernel /vmlinuz root=/dev/sda3 selinux=0 init=/bin/bash initrd /initramfs
所有这些做完之后,执行N遍sync命令,通知内核将改变立即写入磁盘,然后关机或挂起。
新建一个虚拟机,使用在选择磁盘处选择使用刚刚修改的这块磁盘,然后启动。
可以看到grub正常启动了。
bash也正常启动起来了。
可以看到,除了bash的内建命令外,其他的命令都无法执行,所以说这只是一个演示系统启动流程的最简化的Linux系统,距离拥有完备功能的Linux系统还很远。