本文只是为了演示Linux系统启动过程所必要的元素,并非真正意义上的功能完备的Linux系统。

我的环境是VMware虚拟机,CentOS-6.7-x86_64操作系统。


首先为虚拟机添加一块磁盘,我这里使用默认20G,其实不需要这么大,不过虚拟机嘛,你不选立即分配,它也不会真的占那么大空间。


首先对它进行分区,使用MBR分区表。规划三个分区,一个boot分区200M,一个swap分区2G,剩余空间都给根分区。

[root@localhost ~]# parted -s /dev/sdb mklabel msdos
[root@localhost ~]# parted -s /dev/sdb mkpart primary 2048s 200M
[root@localhost ~]# parted -s /dev/sdb mkpart primary 200M 2200M
[root@localhost ~]# parted -s /dev/sdb mkpart primary 2200M 100%
[root@localhost ~]# partx -a /dev/sdb
[root@localhost ~]# mkfs.ext4 /dev/sdb1
[root@localhost ~]# mkswap /dev/sdb2
[root@localhost ~]# mkfs.ext4 /dev/sdb3
[root@localhost ~]# 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的挂载至该目录。

[root@localhost mnt]# mkdir sysroot
[root@localhost mnt]# mount /dev/sdb3 /mnt/sysroot/


在/mnt/sysroot目录下建立FHS目录结构

[root@localhost ~]# cd /mnt/sysroot/
[root@localhost 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

[root@localhost sysroot]# mount /dev/sdb1 /mnt/sysroot/boot
[root@localhost 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。

[root@localhost 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
[root@localhost ~]# 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的内核和伪根文件系统,不搞那么复杂了,版本号都不要了。

[root@localhost boot]# cd /mnt/sysroot/boot
[root@localhost boot]# cp /boot/vmlinuz-2.6.32-573.el6.x86_64 ./vmlinuz
[root@localhost boot]# cp /boot/initramfs-2.6.32-573.el6.x86_64.img ./initramfs
[root@localhost boot]# ls
grub  initramfs  lost+found  vmlinuz


内核启动完成后,还需要启动系统初始化程序,不过真的完成整个系统初始化过程,需要很多其他程序协作,太过复杂。其实也可以随便指定一个别的程序,这里我们为了简化,直接启动一个bash,所以需要把bash移植过去。

[root@localhost ~]# which bash
/bin/bash
[root@localhost ~]# cp /bin/bash /mnt/sysroot/bin/

仅是这样还不够,bash是运行不起来的,它还依赖一些库文件,因此这些库文件也需要移植。

[root@localhost ~]# 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)
[root@localhost ~]# cp /lib64/libtinfo.so.5 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/libdl.so.2 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/libc.so.6 /mnt/sysroot/lib64/
[root@localhost ~]# cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/


现在还缺一个grub的配置文件,可以自己动手一个。因为我们是准备把这块硬盘拆下来,挂到另一个新建的虚拟机上,所以那个新建的虚拟机只有这一块盘,(hd0,0)和/dev/sda3就是这么来的。另外CentOS启动时默认就会加载SELinux,而这个简化的系统什么都没有,所以它会影响启动,要把它关掉。

[root@localhost ~]# 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命令,通知内核将改变立即写入磁盘,然后关机或挂起。


新建一个虚拟机,使用在选择磁盘处选择使用刚刚修改的这块磁盘,然后启动。

wKioL1b3sVqDRPqnAAAnkiSiK7E787.png

可以看到grub正常启动了。


wKiom1b3sQKisBKYAABK3AvlW2s368.png

bash也正常启动起来了。


wKiom1b3sVXjxSUhAAA5Z_fXv1w515.png

可以看到,除了bash的内建命令外,其他的命令都无法执行,所以说这只是一个演示系统启动流程的最简化的Linux系统,距离拥有完备功能的Linux系统还很远。