linux 内核代码学习(九)--Linux内核启动和文件系统

一个比较顺手的学习平台可以达到事半功倍的效果,这里使用的平台环境主要是利用了主机和从机间的文件共享,以及从机自带的编译环境可以比较顺利的编译busybox1.0版本,方便进行内核和文件系统的测试了学习。

主机环境:vmware7.0+win10

从机环境:RedHat9.0 linux发行版

所有的PC机在加电之后,BIOS会寻找到启动盘第一个扇区,并将其复制到RAM中来执行它,对于两种不同的启动方式,这个扇区通常含有两种不同的代码:1、引导程序(比如Lilo或Grub等)的代码,引导程序会帮助定位内核的位置;2、内核的代码,这通常是从软盘启动时使用的引导的方式。对于前者,通常需要内核支持initrd。如果是后者,使用的Boot Loader就是arch/i386/boot/bootsect.S,当内核被编译的时候,这段执行代码就被链接到内核image的最开始的地方,这样很容易就能只要把内核复制到起始位置为第一个扇区的软盘上就能得到可自启动的软盘,内核会初始化设备驱动和内部的数据结构,之后它会到一个特定的位置――Ramdisk Word来获得根文件系统的位置,内核必须知道去那里寻找这个根文件系统,否则它将停机,在使用软盘启动的方式时,内核可以把一个压缩的文件系统释放到RAM中,称之为Ramdisk,这是一个内存区域,但内核会把它当作磁盘一样使用。

我们首先要得到一张可以引导进入linux环境的软盘,这种软盘必须由两部分组成,即内核和根文件系统。我们首先制作一个内核。内核的编译要把内核部分放到一张1.44MB的软盘上去,通常要对内核进行压缩,压缩内核的最好方法是进行重新编译内核,将一些不必要的支持去掉,如对网络和其它周边设备的支持,重要的一点是记住内核必须支持RAMDISK及ext2,否则系统不能正常引导。

一:制作从软盘直接启动的liunx,软盘上包括内核及简单文件系统。

下载linux2.4.20内核源代码,源代码放置在win10主机上,通过vmware的文件共享功能在从机redhat9上进行编译,编译出合适大小的内核。同样先注释掉makefile中下面两行,然后在内核include目录里面根据cpu类型手动拷贝asm目录。

使用vmware工具创建一张虚拟启动软盘,根据内核readme文档说明"If you want to make a boot disk (without root filesystem or LILO), insert a floppy in your A: drive, and do a "make bzdisk". "先创建一张不带文件系统的boot盘,再用vmware创建一个测试从机,插入boot盘,看看在没有根文件系统的时候内核的启动效果:

重新配置内核,对内核配置不熟悉可以参考发行版的内核配置,再次制作引导盘测试,可以看到内核能够正常启动,最后提示没有文件系统:

制作根文件系统:

制作根文件系统前,我们先要解决一个问题:因为一个根文件系统要实现基本的功能,必须包括一些常用工具:如:sh,ls,cd,cat...... 但是常用工具会占用很多空间,要是用原来系统中的这些命令,就是全部用静态编译,不是用动态连接库,大概也要有2MB~3MB,放不进软盘。因此我们的解决的方案是使用BusyBox工具。BusyBox 它包含了七十多种 Linux 上标准的工具程序,只需要的磁盘空间仅仅几百 k 。在嵌入式 系统上常用到它 (例如 Linux Router Project 和 Debian boot floppy就使用到它)。

建立 BusyBox
Index of /downloads上下载busybox-1.00.tar.bz2,在/home目录下解压和安装

首先我们从官方网站上下载BusyBox的最新版本:busybox-1.00-rc3.tar.gz并且解开

#tar zxvf busybox-1.00-rc3.tar.gz

为了压缩空间,我们采用静态编译,可以是使用busybox图形化配置或者修改 Makefile 中的 DOSTATIC 参数为true

DOSTATIC=true

这两个选项是不使用系统的/usr安装目录,当前目录中_install为安装目录。

然后修改 BusyBox 中的 init.c,设定系统要执行的第一个程序为: /etc/rc.d/rc.sysinit,这样做的目的是让制作的启动盘的启动效果同redhat9发行版一样的效果。

#define INIT_SRCIPT \"/etc/rc.d/rc.sysinit\"

#make

#make install

到这一步我们就得到了可执行命令busybox,解决了这个问题后,我们可以开始制作根文件系统。

制作根文件系统:首先为根文件系统建一个目录叫做 floppy-Linux,然后进入 floppy-Linux 目录内

mkdir floppy-Linux

cd floppy-Linux

然后为 root filesystem 建立一些标准的目录

mkdir dev etc etc/rc.d bin proc mnt tmp var

chmod 755 dev etc etc/rc.d bin mnt tmp var

chmod 555 proc

ln -s bin sbin

然后进入 /dev 目录下建立根文件系统必须的一些设备文件。

建立一般终端机设备

mknod tty c 5 0

mknod console c 5 1

chmod 666 tty console

建立 VGA Display 虚拟终端机设备

mknod tty0 c 4 0

chmod 666 tty0

建立 RAM disk 设备

mknod ram0 b 1 0

chmod 600 ram0

建立 floppy 设备

mknod fd0 b 2 0

chmod 600 fd0

建立 null 设备

mknod null c 1 3

chmod 666 null

到这里我们就有了一个初步的小型根文件系统,但是还需要配置一些有关的 shell script来完善它。编辑有关的 shell script:首先进入到 /floppy-Linux/etc/ 这个目录下编辑 inittab,rc.d/rc.sysinit,fstab这三个文件 ,内容分别如下:

inittab

::sysinit:/etc/rc.d/rc.sysinit

::askfirst:/bin/sh

rc.sysinit

#!/bin/sh

mount --a

fstab

proc /proc proc defaults 0 0

然后修改inittab,rc.sysinit,fstab这三个文件的权限

chmod 644 inittab

chmod 755 rc.sysinit

chmod 644 fstab

配置完shell script后,我们注意到这些shell script会使用一些 /bin目录下的命令,但是我们的/bin目录下是空的。现在我们就使用BusyBox来制作这些常用命令。将busybox 复制到软盘的/bin目录下,并且改名为init。

cp busybox /floppy-Linux/bin/init

然后创建常用命令的link,具体的工作原理请参阅busybox的官方说明。

ln -s init ls

ln -s init cp

ln -s init mount

ln -s init umount

ln -s init more

ln -s init ps

ln -s init sh

ln -s init df

现在我们就有了所需的常用命令。

到这里我们的根文件系统就制作完成了,但是和内核一样,要把根文件系统部分放到一张1.44MB的软盘上去,也要进行压缩,下面我们就着手压缩它。

压缩根文件系统:一般我们会采取 RAM Disk 的方式实现。简单的来说就是将准备好的根文件系统压缩成为Ramdisk的镜像文件,当用软盘启动时,再把镜像文件解压到内存中,形成一个虚拟盘(RAMDISK),通过RAMDISK控制系统启动。

我们现在制作Ramdisk的镜像文件

dd if=/dev/zero of=/tmp/tmp_loop bs=1k count=2048

losetup /dev/loop0 /tmp/tmp_loop

mke2fs -m 0 /dev/loop0

mount -t ext2 /dev/loop0 /mnt

cp -a floppy-Linux/* /mnt

umount /mnt

losetup -d /dev/loop0

dd if=/tmp/tmp_loop | gzip -9 > /tmp/Image.gz

rm -f /tmp/tmp_loop

sync

或者

dd if=/dev/zero of=/dev/ram0 bs=1k count=4096

mke2fs /dev/ram0

mount -t ext2 /dev/ram0 ramdisk/

cp -R floppy-Linux/* ramdisk/

umount ramdisk

dd if=/dev/ram0 bs=1k | gzip -v9 > rootfs.gz

这样我们就得到了压缩过的根文件系统也就是Ramdisk的镜像文件rootfs.gz。目前为止我们已经有了内核和压缩过的根文件系统.现在剩下的就是把它们整合在一张软盘里面。根据引导的方式不同,有以下三种整合方案:用grub引导、用sysLinux引导、直接引导。

1.将内核与文件系统放置在一张软盘上

依次执行:

dd if=/mnt/hgfs/linux-2.4.20/arch/i386/boot/bzImage of=/dev/fd0 bs=1k

876+1 records in

876+1 records out

在这个例子中,dd 写入了 876个完整记录(records) + 1个partial record ,所以内核占用了 877 个软盘的blocks 。这个数字称为 KERNEL_BLOCKS ,请记得它,这个数字还要使用。

之后,设置根设备为软盘本身,并且设置根以读写方式装载

#rdev /dev/fd0 /dev/fd0

#rdev -R /dev/fd0 0

上面这个例子表示dd写了876个完整记录和一个部分记录到软盘上,因此内核占用了软盘的前877 个记录块。记住这个数字,然后设置内核的Ramdisk Word。Ramdisk Word可以通过rdev命令设置,它的内容为:

如果15位设置的话,内核在加载文件系统之前会进行提示,这在将内核与文件系统盘分开的情况时是必要的。对于在一张软盘上集成内核和文件系统的情况,需要在0-10位指出ramdisk的偏移,并将14位置1,所以得出的ramdisk word十进制表示为:877 + 2^14 = 877 + 16384 = 17261

#rdev -r /dev/fd0 17261

之后

#dd if=rootfs.gz of=/dev/fd0 bs=1k seek=877

这样一张同时包含内核和文件系统的软盘就成功了。

这样就将linux2.4.20内核和文件系统集成到一张软盘上了,并成功启动linux。

相关推荐
静止了所有花开32 分钟前
SpringMVC学习笔记(二)
笔记·学习
爱吃生蚝的于勒40 分钟前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
L_cl3 小时前
Python学习从0到1 day26 第三阶段 Spark ④ 数据输出
学习
Mephisto.java3 小时前
【大数据学习 | HBASE】hbase的读数据流程与hbase读取数据
大数据·学习·hbase
舞动CPU4 小时前
linux c/c++最高效的计时方法
linux·运维·服务器
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
皮锤打乌龟4 小时前
(干货)Jenkins使用kubernetes插件连接k8s的认证方式
运维·kubernetes·jenkins
钰@5 小时前
小程序开发者工具的network选项卡中有某域名的接口请求,但是在charles中抓不到该接口
运维·服务器·小程序
wanhengwangluo5 小时前
云服务器和物理服务器的区别有哪些?
运维·服务器
尘浮生5 小时前
Java项目实战II基于微信小程序的移动学习平台的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·学习·微信小程序·小程序