在博文“Linux系统启动过程分析”中我们了解了linux系统的启动流程,今天我们就来手动一步一步从头来构建一个最小的linux系统,然后用模拟器将其加载起来。常见的模拟器有Qemu、Bochs、VMWare、VPC、Virtual Box和Xen等,以及特殊的模拟UML(User-Mode-Linux),这里我们选择用VMWare。
我们制作的Linux系统有shell功能,支持Web Server,telnet等服务,以及ifconfig,vi等常见工具。准备工作:
在http://www.kernel.org 下载内核源代码 linux-2.6.21.tar.bz2;
在http://www.busybox.org 下载busybox源码 busybox-1.14.4.tar.bz2。
在本地新建一个目录,例如/home/DIY,当然你可以随便选择,然后将下载的内核源码和busybox源码包拷贝到/home/DIY目录下;
A)、构造根文件系统
我们都知道标准的发行版linux其目录结构一般是如下这个样子:
我们制作的linux运行起来之后当然也应该有个类似的目录结构。这里我们只选择一些必须的目录,因为我们构建的是“最小”的Linux系统。
在/home/DIY目录下依次执行如下命令:
在rootfs/etc目录下分别建立如下各个文件group、inittab、profile、protocols、
rcS和services:
点击(此处)折叠或打开
-
###################### /etc/group ###################### from here
-
root:x:0:
-
ftp:x:800:
-
nogroup:x:65534:
-
-
######################/etc/inittab ###################### from here
-
::sysinit:/etc/rcS
-
tty1::askfirst:-/bin/sh --login
-
tty2::askfirst:-/bin/sh --login
-
tty3::askfirst:-/bin/sh --login
-
-
######################/etc/profile ###################### from here
-
#!/bin/sh
-
-
cat <<EOF
-
-
Welcome to DIY
-
-
EOF
-
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
-
-
######################/etc/protocols ###################### from here
-
# Internet (IP) protocols
-
#
-
ip 0 IP
-
icmp 1 ICMP
-
igmp 2 IGMP
-
ggp 3 GGP
-
ipencap 4 IP-ENCAP
-
st 5 ST
-
tcp 6 TCP
-
egp 8 EGP
-
igp 9 IGP
-
pup 12 PUP
-
udp 17 UDP
-
hmp 20 HMP
-
xns-idp 22 XNS-IDP
-
rdp 27 RDP
-
iso-tp4 29 ISO-TP4
-
xtp 36 XTP
-
ddp 37 DDP
-
idpr-cmtp 38 IDPR-CMTP
-
idrp 45 IDRP
-
rsvp 46 RSVP
-
gre 47 GRE
-
esp 50 IPSEC-ESP
-
ah 51 IPSEC-AH
-
skip 57 SKIP
-
rspf 73 RSPF CPHB
-
vmtp 81 VMTP
-
eigrp 88 EIGRP
-
ospf 89 OSPFIGP
-
ax.25 93 AX.25
-
ipip 94 IPIP
-
etherip 97 ETHERIP
-
encap 98 ENCAP
-
pim 103 PIM
-
ipcomp 108 IPCOMP
-
vrrp 112 VRRP
-
115 L2TP
-
isis 124 ISIS
-
sctp 132 SCTP
-
fc 133 FC
-
-
######################/etc/rcS ###################### from here
-
#!/bin/sh
-
-
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
-
mount -t proc none /proc
-
mount -t sysfs none /sys
-
mount -t tmpfs tmpfs /dev -o size=512K,mode=0755
-
echo DIY > /proc/sys/kernel/hostname
-
-
mkdir -p /var/run /var/log /var/lock /var/state \
-
/var/tmp /var/mnt /dev/pts /dev/shm
-
mount devpts /dev/pts -t devpts
-
-
echo /bin/mdev > /proc/sys/kernel/hotplug
-
mdev -s
-
-
ifconfig lo 127.0.0.1 up
-
ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up
-
-
telnetd -l /bin/sh
-
httpd -h /www
-
-
###################/etc/services ################# from here
-
ssh 22/tcp
-
ssh 22/udp
-
telnet 23/tcp
-
telnet 23/udp
-
http 80/tcp www www-http
-
http 80/udp www www-http
-
login 513/tcp
-
shell 514/tcp cmd
再在rootfs/www目录下建立一个index.html文件,内容如下:
点击(此处)折叠或打开
-
<h1>Success!</h1>
-
<p>Welcome to DIY linux!</p>
最后rootfs目录的组织结构如下:
其他的命令行工具由接下来的busybox生成。
B)、编译busybox
在Linux系统中常用的工具,如 bash、grep命令、sed 命令、telnetd等,这里为了方便省事,我就用busybox来代替了。现在的busybox拥有非常多的工具,真正成为一个“Busy”的box。后面的例子将尝试只使用 busybox来充当所有应用层所需要的工具集。包括Shell,网络配置,web服务器,telnet等。而busybox也由此得到一个称号“嵌入式世界的瑞士军刀”。
将修改后的“ busybox.config.txt ”复制到busybox-1.14.4目录下重命名为“.config”,注意文件名前面的点“.”绝对不能省略。
之后弹出如下界面:
在配置界面下,我们依次选择:Busybox Settings => Build Options 然后选中(按空格键),这里我们将编译生成静态库的busybox,如下图中所示选项:
配置busybox的安装目录,依次选择:Busybox Settings => Installation Options ,如下:
保存配置后执行编译命令make:
编译完成后执行make install:
这样我们编译的busybox工具就安装到前面我们创建的rootfs目录中了,此时rootfs目录下的组织结构就变成了如下这个样子:
不管是bin,sbin,usr/bin还是usr/sbin目录下的命令都是到/bin/busybox应用程序的软连接。目前rootfs这个目录结构和我们常见的linux发行版的目录结构还是有些差异,所以我们继续往rootfs中增加dev,proc,tmp,var,lib,root和sys目录:
这样子就更像一个“标准”linux发行版的样子了。接下来我们来制作一个ramdisk的初始化文件,名为initrd。Linux内置支持以RAM磁盘的形式来启动。关于Linux系统的启动流程请参见博文“Linux系统启动过程分析”里的详细描述。
C)、制作initrd文件
D)、编译Linux内核源码
解压内核源码,然后将我修改后的内核配置文件“ linux.config.txt ”拷贝到linux-2.6.21目录下,重命名为“.config”,如下:
执行make menuconfig可以查看哪些配置项已经被选上:
执行make命令开始编译内核:
我们提供的内核配置文件linux.conf将模块已经静态编译到内核中去了,这样就会造成内核比较大,如果是采用动态加载模块的话,需要将所有模块安装到前面制作的ramdisk里。编译好的内核镜像,一般位于:
• 对于x86平台,压缩后的核心是 arch/x86/boot/bzImage;
• 对于MIPS平台,压缩后的核心是 arch/powerpc/boot/zImage;
• 对于arm平台,压缩后的核心是 arch/arm/boot/zImage
……
E)、用VMWare加载内核
将arch/x86/boot/bzImage和/home/DIY/initrd文件拷贝到linux系统的/boot目录下,然后修改/boot/grub/menu.lst,在其中添加如下一项:
点击(此处)折叠或打开
-
title DIY Your OS
-
root (hd0,0)
-
kernel /bzImage rw root=/dev/ram rootfs_size=8M
-
initrd /initrd
PS:因为我们制作的initrd文件大小就是8M,所以rootfs_size=8M。
重启VMware,在启动界面我们自己built的linux系统:
启动后效果如下:
我们可以看到eth0接口已经up了,其IP地址默认为192.168.1.1,因为我虚拟机的IP地址池是192.168.6.*网段的,所以手动将eth0的接口IP设置为192.168.6.135:
然后通过web和telnet访问我们自己做的系统,最终的访问结果如下:
小结:通过今天的学习相信大家对Linux系统的运行原理和启动流程的认识又上了一个新的台阶,更重要的是学会了如何手动构建一个“最小”的Linux“发行版”系统。那么,现在回过头来再看那些商业版的Linux系统,其实本质和我们今天做工作的差不多,所以,如果有条件我们也可以发行一个自己的系统了:)。