在博文“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
- l2tp 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
点击(此处)折叠或打开
- <h1>Success!</h1>
- <p>Welcome to DIY linux!</p>
其他的命令行工具由接下来的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系统,其实本质和我们今天做工作的差不多,所以,如果有条件我们也可以发行一个自己的系统了:)。