2012-09-10
 
     在博文“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
再在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里。编译好的内核镜像,一般位于:
<!--[if !supportLists]-->?    <!--[endif]-->对于x86平台,压缩后的核心是 arch/x86/boot/bzImage;
<!--[if !supportLists]-->?    <!--[endif]-->对于MIPS平台,压缩后的核心是 arch/powerpc/boot/zImage;
<!--[if !supportLists]-->?    <!--[endif]-->对于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系统,其实本质和我们今天做工作的差不多,所以,如果有条件我们也可以发行一个自己的系统了:)。

从头构建自己的Linux系统的更多相关文章

  1. 构建嵌入式小型Linux系统

    构建嵌入式小型Linux系统 摘要:用buildroot构建x86的交叉编译工具链:裁减linux内核,尽可能做到最小:手工构建根文件系统:安装qemu虚拟机,仿真新配置的Linux系统:为新配置的L ...

  2. 《手把手教你构建自己的 Linux 系统》学习笔记(10)

    目录 /etc/fstab 文件的作用是什么? Linux 内核的图形化启动是怎么回事? Linux 系统中的文件名是否以大小写来进行区别? 「GRUB 中无法找到硬盘」怎么解决? 「GRUB 及配置 ...

  3. 《手把手教你构建自己的 Linux 系统》学习笔记(9)

    目录 autoreconf 命令的作用是什么? aclocal automake -a autoconf 一条命令搞完三面三步 既然有其他的「编译控制软件」为何还是使用 make 来进行编译控制? M ...

  4. 《手把手教你构建自己的 Linux 系统》学习笔记(8)

    目录 Binutils 软件包有什么用? make -k 的作用是什么? man-pages 里有几种文档?分别表示什么意思? 如何查询指定目录的 man-pages ? 如何使用 make 命令的同 ...

  5. 《手把手教你构建自己的 Linux 系统》学习笔记(6)

    目录 /dev 目录是干什么的? /proc 和 /sys 目录是干什么的? udev 这个软件是干什么用的? 目录映射是临时性的,还是永久性的? 命令行里大括号 "{}" 的作用 ...

  6. 《手把手教你构建自己的 Linux 系统》学习笔记(5)

    交叉编译是什么? 交叉编译就是在一个系统上,编译生成另外一个系统运行的程序文件. 「硬件体系结构」和「操作系统」的关系是什么? 硬件体系结构也可以称为架构,主要是通过 CPU 的指令集来进行区分的,操 ...

  7. 《手把手教你构建自己的 Linux 系统》学习笔记(2)

    Linux 系统定制原理 虚拟根目录 我们的目标是为了完成目标系统(也就是我们要做的系统),他是一个可以独立运行的系统,不依赖雨主系统和临时系统,根据 Linux 系统的特点它需要存放在根目录下面,但 ...

  8. 《手把手教你构建自己的 Linux 系统》学习笔记(1)

    第二章.基础准备--Linux 系统定制原理 Linux 系统的组成及架构 共享库和静态库 在 Linux 系统中,函数库包含两种形式:共享库和静态库. 共享库 共享库在程序运行时,为其提供所需要的函 ...

  9. 《手把手教你构建自己的 Linux 系统》学习笔记(7)

    目录 tee 命令的缺陷是什么?如何解决这个缺陷? /etc/ld.so.conf 文件的作用是什么? 动态链接和静态链接有什么不同? 动态编译 静态编译 共享库为什么会有版本?共享库的版本升级原理是 ...

随机推荐

  1. 自旋锁-SpinLock(.NET 4.0+)

    短时间锁定的情况下,自旋锁(spinlock)更快.(因为自旋锁本质上不会让线程休眠,而是一直循环尝试对资源访问,直到可用.所以自旋锁线程被阻塞时,不进行线程上下文切换,而是空转等待.对于多核CPU而 ...

  2. javax.persistence.PersistenceException: No Persistence provider for EntityManager named ...

    控制台下输出信息 原因:persistence.xml必须放在src下META-INF里面. 若误放在其他路径,就会迷路.

  3. Win10年度更新开发必备:VS2015 Update 3正式版下载汇总

    微软在06月27日发布了Visual Studio 2015 Update 3 .在MSDN中微软也提供下载,而且MSDN的Visual Studio 2015 Update 3与官方免费下载的文件是 ...

  4. 转:nginx基础概念(request)

    这节我们讲request,在nginx中我们指的是http请求,具体到nginx中的数据结构是ngx_http_request_t.ngx_http_request_t是对一个http请求的封装. 我 ...

  5. celery简单应用

    写作背景介绍 在celery简单入门中已经介绍了写作的背景,这篇文章主要是深入介绍celery的使用技巧.在实际的项目中我们需要明确前后台的分界线,因此我们的celery编写的时候就应该是分成前后台两 ...

  6. atitit.无线网卡 不能搜索到WiFi 无线路由信号的解决不能上网

    atitit.无线网卡 不能搜索到WiFi 无线路由信号的解决不能上网 #---现象 pc机无线网卡不能搜索到无线路由信号.. 但是笔记本和手机是可以的... 不过pc机无线网卡能搜索到别的路由的信号 ...

  7. python web框架——扩展Django&tornado

    一 Django自定义分页 目的:自定义分页功能,并把它写成模块(注意其中涉及到的python基础知识) models.py文件 # Create your models here. class Us ...

  8. Android:改变Activity切换方式(转载)

    overridePendingTransition(enterAnim, exitAnim); Intent intent =new Intent(this,item2.class); startAc ...

  9. SCN试验之一

    在数据库运行的时候,数据库系统的SCN不断地增长: SQL> select dbms_flashback.get_system_change_number from dual; GET_SYST ...

  10. C/C++在Java项目、Android和Objective-C三大平台下实现混合编程

    Android和iOS开发都支持C++开发,可以一套代码多平台使用.同时C++难以反编译的特性也可以为Android开发带来代码的保密,另一native特性也可以提高代码的运行效率. 一.为什么使用C ...