手把手带你自制Linux系统之六 编译内核及busybox完成系统定制

手把手带你自制Linux系统之六 编译内核及busybox完成系统定制

重新看了一下前面的几章,发现其实前面的5章一直围绕一个话题讲解 — 如何利用CentOS现有资源组装一个Linux。这种方式十分拙劣,Linux内核是固化的、initrd没有充分精简、命令需要一个一个拷贝,最终做出来的Linux不能算是完全定制的。

这一章就来自己编译Linux源码生成内核,使用busybox源码制作initrd及跟文件系统,完全从头开始制作一个真正定制的Linux。

并不是说前面的几章就没有意义,本章虽然从头开始,但其中依然会用到很多前面几章已经讲过做过的步骤,前面的章节讲解很多Linux启动的原理,所以从第一章开始的每一章都是必不可少的。

下面就按照Linux系统启动顺序来从头开始制作。

1. 创建分区

将准备好的磁盘分区并格式化,具体步骤查看 第二章第一步。

格式化完成后得到两个分区, /dev/hda1 大小 20M, /dev/hda2 大小 512M。

分别挂载至/mnt/boot和 /mnt/sysroot。

2. 安装GRUB

使用grub-install 命令安装grub,指定根路径为/mnt,设备为/dev/hda
grub-install --root-directory=/mnt /dev/hda

创建grub配置文件
vi /mnt/boot/grub/grub.conf

内容如下,root(grub root)为第一块磁盘的第一个分区,kernel使用vmlinuz,initrd使用 initrd.gz
default=0
timeout=5
title MiniLinux (2.6.38.5)
    root (hd0,0)
    kernel /vmlinuz ro root=/dev/hda2
    initrd /initrd.gz

3. 编译kernel

这里使用的是 linux-2.6.38.5.tar.bz2,下载地址:
https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.5.tar.gz

将下载完成后文件解压到 /usr/src下,创建一个软链接指向linux-2.6.28.5
cd /usr/src
ln -s linux-2.6.28.5 linux

复制我提供的config文件: config-2.6.38.5-1.miniLinux ,其中已经精简了许多用不到的模块。
cd linux
cp config-2.6.38.5-1.miniLinux .config

如果还有其它特殊需求,使用make menuconfig可以打开配置界面。
如修改local version:
make menuconfig
 General setup  --->     Local version

开始编译
make SUBDIR=arch/

内核编译完成后,生成的arch/x86/boot/bzImage 就是需要的内核文件vmlinuz,将它拷贝到boot下
cp /usr/src/linux/arch/x86/boot/bzImage /mnt/boot/vmlinuz

4. 制作initrd

busybox体积娇小,功能强大,不仅适合用来做根文件系统,也同样适合做initrd。

编译busybox
这里使用1.23.2版本,下载地址:
https://busybox.net/downloads/busybox-1.23.2.tar.bz2
下载完成后解压busybox-1.23.2.tar.bz2

这个版本的busybox依赖一个高版本Linux内核中的头文件,从上一步解压得到的2.6.28.5内核源码中拷贝过来。
cd busybox-1.23.2
mkdir include/mtd
cp /usr/src/linux-2.6.28.5/include/mtd/ubi-user.h include/mtd


配置busybox为静态编译模式

make menuconfig
Busybox Settings  ---> Build Options  ---> [*] Build BusyBox as a static binary (no shared libs)
勾选build busybox as a static binary,静态编译busybox

编译并安装,默认安装在busybox目录下的_install
make install

拷贝busybox安装目录下的文件到临时目录,开始制作initrd
mkdir /tmp/initrd/
cd /tmp/initrd/
cp /root/busybox-1.23.2/_install -a .

创建几个必要目录
mkdir proc sys mnt/sysroot dev tmp etc -pv

创建设备文件console和null
mknod dev/console c 5 1
mknod dev/null c 1 3

移除linuxrc,创建init脚本文件
rm linuxrc
vi init

init脚本的主要工作是加载内核访问真正的根文件系统所在设备需要的驱动,然后切换到真正的根。
不过在上一步编译内核时, 已经把ext3文件系统的驱动做进了内核,这里就需要加载ext3驱动了。
init内容如下:
#!/bin/sh

echo "Mounting proc and sys..."
mount -t proc proc /proc
mount -t sysfs sysfs /sys

echo "Detect and export hardware infomation..."
mdev -s

echo "Mount real rootfs to /sysroot..."
mount -t ext3 -o ro /dev/hda2 /sysroot

echo "Switch to real rootfs..."
exec chroot /sysroot /sbin/init

给init脚本添加可执行权限
chmod +x init

将/tmp/initrd中的所有文件打包并压缩为initrd.gz
find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz

5. 制作根文件系统


制作根文件系统同样需要用到上一步的busybox。

拷贝busybox安装后的文件到/dev/hda2
cd /mnt/sysroot
cp /root/busybox-1.23.2/_install -a .
rm linuxrc

创建根文件系统必需的路径
mkdir boot dev etc/rc.d/init.d home lib/modules mnt proc root sbin sys tmp var/{lock,run,log} -pv

创建设备文件console、null
mknod dev/console c 5 1
mknod dev/null c 1 3

创建inittab文件
vi inittab

busybox中的init没有启动级别的概念,所以使用的inittab文件与一般的sysvinit、upStart使用的格式有一些出入,内容如下:
::sysinit:/etc/rc.d/rc.sysinit
::respawn:/sbin/getty 9600 tty1
::respawn:/sbin/getty 9600 tty2
::shutdown:/bin/umount -a -r
::ctrlaltdel:/sbin/reboot

添加登录认证功能
需要创建3个文件: passwd, shadow, group
grep "^root\>" /etc/passwd > /mnt/sysroot/etc/passwd
grep "^root\>" /etc/shadow> /mnt/sysroot/etc/shadow
grep "^root\>" /etc/group> /mnt/sysroot/etc/group

busybox没有提供bash,只有ash,修改passwd中/bin/bash为/bin/sh
vi /mnt/sysroot/etc/passwd
内容
root:x:0:0:root:/root:/bin/sh

创建系统初始化脚本文件 rc.sysinit
vi /mnt/sysroot/etc/rc.d/rc.sysinit

内容如下:
#!/bin/sh
#
echo -e "\tWelcome to \033[31mMy Mini Linux \033[0m"

下面一点一点在rc.sysinit中加入内容

挂载proc和sysfs 虚拟文件系统
echo "Mount proc and sys..."
mount -t proc proc /proc
mount -t sysfs sysfs /sys

以读写方式重新挂载根文件系统
echo "Remount the rootfs..."
mount -t ext3 -o remount,rw /dev/hda2 /

动态管理设备文件,busybox提供了mdev,用法和功能同udev一样
echo "Detect and export hardware infomation..."
mdev -s

挂载fstab中描述的其它文件系统
echo "Mount the other filesystem..."
mount -a

rc.sysinit添加可执行权限
chmod +x rc.sysinit

fstab文件内容如下:
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
/dev/hda1               /boot                   ext3    defaults        0 0
/dev/hda2               /                       ext3    defaults        1 1

6. 添加网络功能

需要的步骤
初始化网卡驱动(rc.sysinit中安装驱动模块) -> 配置网卡(由/etc/rc.d/init.d/network脚本负责)

具体参考第四章
http://blog.csdn.net/toormi/article/details/50327159
有一点小区别的是,自己编译得到pcnet32.ko模块不依赖其他模块。pcnet32.ko路径在 /usr/src/linux/drivers/net/pcnet32.ko

7. 一些细节小功能的完善


设置主机名
rc.sysinit中添加
echo "Set the hostname"
[ -f /etc/hostname ] && . /etc/hostname
[ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && HOSTNAME = localhost

在/etc 下创建hostname文件用来保存HOSTNAME变量
vi etc/hostname
内容
HOSTNAME="minilinux"

添加登录前提示信息
vi etc/issue

内容
Mini Linux (2.6.38.5)
Kernel \r on an \m

  设置终端提示符
设置环境变量PS1即可设置提示字符串。但是 ash使用的 配置文件 与bash不一样,ash可以使用/etc/profile和~/.profile两个文件。为了对全部用户生效,在/etc/profile中添加PS1变量。

vi etc/profile
内容
export PS1='[\u@\h \W]\\$ '

其中\u等符号会分别被替换
\u - user,用户名
\h - hostname,主机名
\W - current path,当前路径
\\$ - 提示符,root 为#,其它为$

8. 测试

启动后一切正常,如图所示:
手把手带你自制Linux系统之六 编译内核及busybox完成系统定制_第1张图片


总结

    本章使用自己编译的linux内核以及busybox制作出了一个Linux小系统。与前面使用系统中现成资源组装起来的Linux系统相比,本章自己造轮子的方式才算是完成了真正意义上的自制。
    这种方式制作出来的系统有很多的优点, 能够根据自己的需要对系统进行裁剪优化; busybox集成了大多数常用命令,不需要 一个一个的移植 需要的命令; 使用busybox制作的initrd和跟文件系统更加的小巧,启动速度也更块。
    busybox中虽然功能很齐全,但还是有一些常用工具没有提供,比如bash。而且大都是其他命令的简化版本,如果想要使用更强大的功能也是需要单独移植。

    本章的完结也代表着本系列教程的完结,看了一下日期从8月份开始第一章,到现在日历都已经翻到了2016,才终于完成。中间有2个月工作比较忙,耽误了一下。不过这样算下来效率还是不高,因为文章中的大部分都是马哥讲到的,我主要是调整了一下顺序,分了一下章节,查了一下资料,补充了一小下。整个教程做下来,我自己也学到了很多关于Linux的东西,明白了/etc下辣么多文件都是用来干嘛的。也真心希望这个教程可以帮助到其他和我一样热爱Linux,以及想要通过做一个小的Linux的方式来学习Linux系统的朋友。

教程用到的主要文件已经上传github: 
https://github.com/ma3232335/MiniLinux.git

你可能感兴趣的:(手把手带你自制Linux系统)