分享

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

 qweertt4747 2017-02-07
手把手带你自制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
[plain] view plain copy
  1. grub-install --root-directory=/mnt /dev/hda  

创建grub配置文件
[plain] view plain copy
  1. vi /mnt/boot/grub/grub.conf  

内容如下,root(grub root)为第一块磁盘的第一个分区,kernel使用vmlinuz,initrd使用 initrd.gz
[plain] view plain copy
  1. default=0  
  2. timeout=5  
  3. title MiniLinux (2.6.38.5)  
  4.     root (hd0,0)  
  5.     kernel /vmlinuz ro root=/dev/hda2  
  6.     initrd /initrd.gz  

3. 编译kernel

这里使用的是 linux-2.6.38.5.tar.bz2,下载地址:

将下载完成后文件解压到 /usr/src下,创建一个软链接指向linux-2.6.28.5
[plain] view plain copy
  1. cd /usr/src  
  2. ln -s linux-2.6.28.5 linux  

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

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

开始编译
[plain] view plain copy
  1. make SUBDIR=arch/  

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

4. 制作initrd

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

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

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


配置busybox为静态编译模式

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

编译并安装,默认安装在busybox目录下的_install
[plain] view plain copy
  1. make install  

拷贝busybox安装目录下的文件到临时目录,开始制作initrd
[plain] view plain copy
  1. mkdir /tmp/initrd/  
  2. cd /tmp/initrd/  
  3. cp /root/busybox-1.23.2/_install -a .  

创建几个必要目录
[plain] view plain copy
  1. mkdir proc sys mnt/sysroot dev tmp etc -pv  

创建设备文件console和null
[plain] view plain copy
  1. mknod dev/console c 5 1  
  2. mknod dev/null c 1 3  

移除linuxrc,创建init脚本文件
[plain] view plain copy
  1. rm linuxrc  
  2. vi init  

init脚本的主要工作是加载内核访问真正的根文件系统所在设备需要的驱动,然后切换到真正的根。
不过在上一步编译内核时,已经把ext3文件系统的驱动做进了内核,这里就需要加载ext3驱动了。
init内容如下:
[plain] view plain copy
  1. #!/bin/sh  
  2.   
  3. echo "Mounting proc and sys..."  
  4. mount -t proc proc /proc  
  5. mount -t sysfs sysfs /sys  
  6.   
  7. echo "Detect and export hardware infomation..."  
  8. mdev -s  
  9.   
  10. echo "Mount real rootfs to /sysroot..."  
  11. mount -t ext3 -o ro /dev/hda2 /sysroot  
  12.   
  13. echo "Switch to real rootfs..."  
  14. exec chroot /sysroot /sbin/init  

给init脚本添加可执行权限
[plain] view plain copy
  1. chmod +x init  

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

5. 制作根文件系统


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

拷贝busybox安装后的文件到/dev/hda2
[plain] view plain copy
  1. cd /mnt/sysroot  
  2. cp /root/busybox-1.23.2/_install -a .  
  3. rm linuxrc  

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

创建设备文件console、null
[plain] view plain copy
  1. mknod dev/console c 5 1  
  2. mknod dev/null c 1 3  

创建inittab文件
[plain] view plain copy
  1. vi inittab  

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

添加登录认证功能
需要创建3个文件:passwd, shadow, group
[plain] view plain copy
  1. grep "^root\>" /etc/passwd > /mnt/sysroot/etc/passwd  
  2. grep "^root\>" /etc/shadow> /mnt/sysroot/etc/shadow  
  3. grep "^root\>" /etc/group> /mnt/sysroot/etc/group  

busybox没有提供bash,只有ash,修改passwd中/bin/bash为/bin/sh
[plain] view plain copy
  1. vi /mnt/sysroot/etc/passwd  
内容
[plain] view plain copy
  1. root:x:0:0:root:/root:/bin/sh  

创建系统初始化脚本文件rc.sysinit
[plain] view plain copy
  1. vi /mnt/sysroot/etc/rc.d/rc.sysinit  

内容如下:
[plain] view plain copy
  1. #!/bin/sh  
  2. #  
  3. echo -e "\tWelcome to \033[31mMy Mini Linux \033[0m"  

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

挂载proc和sysfs 虚拟文件系统
[plain] view plain copy
  1. echo "Mount proc and sys..."  
  2. mount -t proc proc /proc  
  3. mount -t sysfs sysfs /sys  

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

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

挂载fstab中描述的其它文件系统
[plain] view plain copy
  1. echo "Mount the other filesystem..."  
  2. mount -a  

rc.sysinit添加可执行权限
[plain] view plain copy
  1. chmod +x rc.sysinit  

fstab文件内容如下:
[plain] view plain copy
  1. sysfs                   /sys                    sysfs   defaults        0 0  
  2. proc                    /proc                   proc    defaults        0 0  
  3. /dev/hda1               /boot                   ext3    defaults        0 0  
  4. /dev/hda2               /                       ext3    defaults        1 1  

6. 添加网络功能

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

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

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


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

在/etc 下创建hostname文件用来保存HOSTNAME变量
[plain] view plain copy
  1. vi etc/hostname  
内容
[plain] view plain copy
  1. HOSTNAME="minilinux"  

添加登录前提示信息
[plain] view plain copy
  1. vi etc/issue  

内容
[plain] view plain copy
  1. Mini Linux (2.6.38.5)  
  2. Kernel \r on an \m  

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

[plain] view plain copy
  1. vi etc/profile  
内容
[plain] view plain copy
  1. export PS1='[\u@\h \W]\\$ '  

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

8. 测试

启动后一切正常,如图所示:


总结

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

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

教程用到的主要文件已经上传github: 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多