Linux kernel的定制与微型linux系统实现
实验与实验环境介绍
通过vmware workstation10 软件,实现inux kernel的定制,并用这个定制的kernel 结合 busybox做成一个微型的linux系统,同时添加dropbear实现sshd服务。
实验环境:
实验过程简单描述:
1.1)在宿主机Test02上添加2G全新磁盘TTT.vmdk(.vmdk是vmware 虚拟机软件的专用的磁盘文件格式),划分为2个分区:分区A挂载至宿主机/mnt/boot目录下(挂载点目录名一定为boot,牵涉到grub程序的安装),用于安装grub和放置kernel,用于启动分区。分区B挂载至宿主机/mnt/sysroot下,给其移植编译好busybox,dropbear,nginx和相应的启动脚本文件。
wKioL1VgMtKicuEgAAKGmwYzGeE144.jpg
1.2)挂起宿主机Test02,让测试机Test64加载TTT.vmdk磁盘做为系统盘启动。
wKioL1VgNNeT644QAAI84X2XLhc274.jpg
1.3)检查测试机Test64上linux是否正常启动,sshd和nginx是否提供服务。
实验可能会出现的问题与疑问:
上述TTT.vmdk磁盘在2个虚拟机上都被加载使用,在2台机器间测试切换时,会出现磁盘文件系统错误,需重做分区文件系统,当然做好使用cpio命令将已有数据copy出来,在下文第七项中提供有恢复文件系统的脚本。
因为Test02与Test都是同一个vmware workstation软件虚拟出的机器,因此不存在硬件平台差异,不存在需要交叉编译的情况,应用程序可直接互相移植使用。
centos 6.6上系统的启动流程
主板POST加电自检
根据BIOS中boot sequence的设定寻找第一可启动设备
启动第一个可引导启动设备的MBR 中的bootloader(通常为grub,完成1,1.5,2三个部分的加载)
加载并展开 kernel,根据ramdisk的协助,完成根文件系统的只读加载,识别和启动硬件
启动第一个系统进程/sbin/init,设定默认运行级别,使用/etc/rc.d/rc.sysinit脚本进行系统初始化
分别关闭和启动对应级别的所有服务
启动字符终端
启动图形终端(如果默认级别为5
显示登录提示;
注意:
(1) CentOS 6的init程序为upstart,其配置文件为/etc/init/*.conf;此些配置遵循upstart语法格式进行编程;
(2) CentOS 6的服务控制事实上大多数并没有使用upstart脚本来控制,而依然使用的是SysV风格的脚本;
在这个实验中验证2.3)~2.9)的过程。
启动分区设置:
3.1)在宿主机Test02上对TTT.vmdk磁盘进行分区和格式化
wKiom1VgN6Pjyl0jAATF6FiMddI467.jpg
[root@Test02 ~]# fdisk /dev/sdb
wKiom1VgOEbTgefoAAKDFtF0jrE628.jpg
分别格式化为ext4 文件系统:
**一定要记住这里的文件系统类型,后边指定kernel支持的文件系统类型时要用到。
[root@Test02 ~]# mke2fs -t ext4 /dev/sdb1
[root@Test02 ~]# mke2fs -t ext4 /dev/sdb2
wKioL1VgOtyAyL1NAAJS99qqakc639.jpg
3.2)建立挂载点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#建立挂载点/mnt/boot用于挂载/dev/sdb1
#/dev/sdb1是用于测试机Test64的启动分区使用,需要安装grub,故这里的挂载点名必须为boot。
#/dev/sdb2是用于测试机Test64的根分区使用。
[root@Test02 ~]# mkdir /mnt/{boot,sysroot}
[root@Test02 ~]# mount -t ext4 /dev/sdb1 /mnt/boot
[root@Test02 ~]# mount -t ext4 /dev/sdb2 /mnt/sysroot/
[root@Test02 ~]# tree /mnt
/mnt
├── boot
│ └── lost+found
└── sysroot
└── lost+found
4 directories, 0 files
[root@Test02 ~]#
3.3)给/dev/sdb1安装grub
1
2
3
4
5
6
7
8
9
10
[root@Test02 ~]# grub-install --root-directory=/mnt /dev/sdb
Probing devices to guess BIOS drives. This may take a long time.
Installation finished. No error reported.
This is the contents of the device map /mnt/boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.
(fd0) /dev/fd0
(hd0) /dev/sda
(hd1) /dev/sdb
[root@Test02 ~]#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@Test02 ~]# tree /mnt/boot
/mnt/boot
├── grub
│ ├── device.map
│ ├── e2fs_stage1_5
│ ├── fat_stage1_5
│ ├── ffs_stage1_5
│ ├── iso9660_stage1_5
│ ├── jfs_stage1_5
│ ├── minix_stage1_5
│ ├── reiserfs_stage1_5
│ ├── stage1
│ ├── stage2
│ ├── ufs2_stage1_5
│ ├── vstafs_stage1_5
│ └── xfs_stage1_5
└── lost+found
2 directories, 13 files
[root@Test02 ~]#
到此刻启动分区还是不完整的因为缺少kernel和grub的启动配置文件。
定制kernel:
4.1)指定定制思路
在这个实验中将kernel的必要功能直接做进内核,而不是将功能做成模块。暂时在微型linux系统中用不到的功能暂且不做任何处理。
这样在启动微型linux时就不需要ramdisk给kernel提供支持。
4.2)观察宿主机硬件平台类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
[root@Test02 linux]# lspci | egrep --color '(Ethernet|SCSI|PCI)'
00:01.0 PCI bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (rev 01)
00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)
00:11.0 PCI bridge: VMware PCI bridge (rev 02)
00:15.0 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.1 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.2 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.3 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.4 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.5 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.6 PCI bridge: VMware PCI Express Root Port (rev 01)
00:15.7 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.0 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.1 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.2 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.3 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.4 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.5 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.6 PCI bridge: VMware PCI Express Root Port (rev 01)
00:16.7 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.0 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.1 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.2 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.3 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.4 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.5 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.6 PCI bridge: VMware PCI Express Root Port (rev 01)
00:17.7 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.0 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.1 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.2 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.3 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.4 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.5 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.6 PCI bridge: VMware PCI Express Root Port (rev 01)
00:18.7 PCI bridge: VMware PCI Express Root Port (rev 01)
02:00.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:02.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01)
02:03.0 Multimedia audio controller: Ensoniq ES1371 / Creative Labs CT2518 [AudioPCI-97] (rev 02)
#可以观察到网卡为Inter Gigabit Ethernet
#SCSI控制器类型为:LSI,MPT
#总线为PCI总线
需要上述观察结果制定出kernel支持的功能:
将kernel功能直接做进内核
CPU类:
64位kernel
指定cpu类型
支持内核模块卸载
总线类:
总线中支持PCI总线
对设备的支持:
支持scsi驱动和scsi硬盘
支持Fusion MPT device
支持键盘和鼠标做为输入设备
支持USB2.0功能
对文件系统和二进制程序支持:
支持ext4文件系统
支持ELF格式的二进制文件
对网络的支持:
支持TCP/IP协议栈
支持inter Gigabit网卡
清空kernel默认的设定,所需功能挨个定制
[root@Test02 linux]# make allnoconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/zconf.lex.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
scripts/kconfig/conf --allnoconfig Kconfig
#
# configuration written to .config
#
[root@Test02 linux]#
#要保证宿主机上已安装有下列开发组件:
"Server Platform Development"
"Development tools"
使用tab键选择-->save保存设定
使用tab键选择-->exit选择退出
1
2
3
4
5
6
7
#进行编译,保存为bzip2压缩的文件,名为bzImage
[root@Test02 linux]# make bzImage
Setup is 13628 bytes (padded to 13824 bytes).
System is 2092 kB
CRC 4e20c446
Kernel: arch/x86/boot/bzImage is ready (#1)
[root@Test02 linux]#
4.4)复制内核至/mnt/boot目录下并提供grub文件
1
2
3
4
5
6
7
8
9
10
11
[root@Test02 linux]# cp -a arch/x86/boot/bzImage /mnt/boot/
[root@Test02 linux]# cd /mnt/boot
[root@Test02 boot]# ls
bzImage grub lost+found
[root@Test02 boot]# cd grub/
[root@Test02 grub]# vim grub.conf
timeout=3
default=0
title PirateLi
root (hd0,0)
kernel /bzImage ro root=/dev/sda2 init=/bin/bash
4.5)提供/mnt/sysroot下的必要的目录和程序用于测试内核
1
2
3
4
5
6
7
8
9
10
11
[root@Test02 sysroot]# pwd/mnt/sysroot
2
3
4
5
6
7
8
9
10
11
12
13
[root@Test02 sysroot]# vi /mnt/sysroot/sbin/init
#!/bin/bash
echo -e "\tWeclome to \033[31;1mPirateLi Home\033[0m"
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t devtmpfs none /dev/
mount -n -o remount,rw /dev/sda2 /
/bin/bash
[root@Test02 sysroot]# chmod +x /mnt/sysroot/sbin/init
[root@Test02 sysroot]# sync
[root@Test02 sysroot]# sync
[root@Test02 sysroot]# sync
[root@Test02 sysroot]# sync
4.6)挂起宿主机,启动测试机并观察
*注意不要在宿主机和测试机之间切换过快
wKiom1VgVy_RzunDAAN5JMuVG8Q893.jpg
但是不能通过命令关机,只能强制关机
五 编译busybox提供微linux的'身体'
5.1)安装glibc-static和glibc-util
#不安装这两个包很难讲程序编译为静态连接库文件
1
[root@Test02 source]# yum -y install glibc-static glibc-utils
5.2)编译busybox
*注意要将busybox依赖的库文件编译为静态链接库
1
2
3
4
5
6
[root@Test02 source]# tar -xf busybox-1.22.1.tar.bz2
[root@Test02 source]# cd busybox-1.22.1[root@Test02 busybox-1.22.1]# make menuconfig
Busybox Settings
-->Build Options
--->[*]Build BusyBox as a static binary (no shared libs)
[root@Test02 busybox-1.22.1]# make && make install
**这样的话busybox默认安装在解压目录的_install中
1
2
3
[root@Test02 busybox-1.22.1]# ls _install/
bin linuxrc sbin usr
[root@Test02 busybox-1.22.1]#
5.3)清整/mnt/sysroot
1
2
3
4
5
6
7
8
9
10
#清理/mnt/sysroot
[root@Test02 mnt]# pwd
/mnt
[root@Test02 mnt]# fuser -km sysroot
/sysroot/: 2242c
[root@Test02 mnt]# umount sysroot/
[root@Test02 mnt]# mke2fs -t ext4 /dev/sdb2
[root@Test02 mnt]# mount /dev/sdb2 /mnt/sysroot/
[root@Test02 sysroot]# ls
lost+found
1
2
3
4
5
6
#复制busybox至/mnt/sysroot下并创建不存在的目录
[root@Test02 sysroot]# cp -a /root/source/busybox-1.22.1/_install/* .
[root@Test02 sysroot]# ls
bin linuxrc lost+found sbin usr
[root@Test02 sysroot]# rm -rf linuxrc
[root@Test02 sysroot]# for i in $(ls /);do [ -d /mnt/sysroot/$i ]|| mkdir /mnt/sysroot/$i ;done
1
2
3
[root@Test02 sysroot]# ls
bin dev home lib64 media mnt opt root selinux sys usr
boot etc lib lost+found misc net proc sbin srv tmp var
5.4)提供/mnt/sysroot/etc/inittab文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@Test02 sysroot]# cd etc
[root@Test02 etc]# ls
[root@Test02 etc]# touch inittab
[root@Test02 etc]# vim inittab
#使用init加载/etc/rc.d/rc.sysinit初始化系统
::sysinit:/etc/rc.d/rc.sysinit
#开启3个虚拟控制台,这是busybox的写法,不要问why
tty1::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
#定义ctrl+alt+delete为重启系统快捷键
::ctrlaltdel:/sbin/reboot
#关机之前先卸载已挂载的文件系统
::shutdown:/bin/umount -a -r
5.5)提供/mnt/sysroot/etc/rc.d/rc.sysinit文件用户初始化系统
1
2
3
4
5
6
7
8
9
10
11
12
[root@Test02 sysroot]# cd etc
[root@Test02 etc]# mkdir rc.d
[root@Test02 etc]# touch rc.d/rc.sysinit
[root@Test02 etc]# chmod +x rc.d/rc.sysinit
[root@Test02 etc]# vim rc.d/rc.sysinit
#!/bin/sh
echo -e "\t Welcome to \033[31;1mPriate Li Home\033[0m"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mount -n -o remount,rw /dev/sda2 /
/sbin/mdev -s
5.6)修改/mnt/boot/grub/grub.conf文件
1
2
3
4
5
6
[root@Test02 etc]# vim /mnt/boot/grub/grub.conf
timeout=3
default=0
title PirateLi
root (hd0,0)
kernel /bzImage ro root=/dev/sda2 init=/sbin/init
5.7)宿主机同步后挂起,启动测试机
1
2
[root@Test02 etc]# sync
[root@Test02 etc]# sync
wKiom1VgZ8GDt5t4AAPZmHAOJLE096.jpg
现在敲回车就可进入,使用命令poweroff进行关机
5.8)启动网络,设定lo和eth0网卡地址和主机名
使用poweroff命令关闭测试机,进入宿主机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@Test02 ~]# cd /mnt/sysroot/
[root@Test02 sysroot]# vim etc/rc.d/rc.sysinit
#!/bin/sh
echo -e "\t Welcome to \033[31;1mPriate Li Home\033[0m"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mount -n -o remount,rw /dev/sda2 /
/sbin/mdev -s
#设定ifconfig命令启动lo 和eth0 网卡
/sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up
/sbin/ifconfig eth0 192.168.100.30 netmask 255.255.255.0 up
#设定主机名
[ -r /etc/sysconfig/network ]&&source /etc/sysconfig/network
[ -n $HOSTNAME ]&&/bin/hostname $HOSTNAME || /bin/hostname localhost
5.9)编写/mnt/sysroot/etc/sysconfig/network文件
1
2
3
[root@Test02 sysroot]# mkdir etc/sysconfig
[root@Test02 sysroot]# vim etc/sysconfig/network
HOSTNAME=Test64.lijun.com
5.10)编写/etc/fstab文件挂载文件系统
1
2
3
4
5
6
7
[root@Test02 sysroot]# vim etc/fstab
[root@Test02 sysroot]# vim etc/fstab
/dev/sda1 /boot ext4 defaults 0 0
/dev/sda2 / ext4 defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
none /dev/ devtmpfs defaults 0 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#在rc.sysinit脚本中添加mount -a 保证能根据/etc/fstab中设定挂载文件系统
[root@Test02 sysroot]# vim etc/rc.d/rc.sysinit
#!/bin/sh
echo -e "\t Welcome to \033[31;1mPriate Li Home\033[0m"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mount -n -o remount,rw /dev/sda2 /
/sbin/mdev -s
/sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up
/sbin/ifconfig eth0 192.168.100.30 netmask 255.255.255.0 up
[ -r /etc/sysconfig/network ]&&source /etc/sysconfig/network
[ -n $HOSTNAME ]&&/bin/hostname $HOSTNAME || /bin/hostname localhost
mount -a
5.11)同步并挂起宿主机,启动测试机
wKioL1VgbrGg-GhQAANCYeIxX0U212.jpg
wKioL1VgbsGjs7pKAAEv5-v0LiQ875.jpg
5.12)设定passwd,shadow,nsswitch文件,实现用户认证登陆
1
2
3
4
5
[root@Test02 ~]# cd /mnt/sysroot/
[root@Test02 sysroot]# touch etc/passwd
[root@Test02 sysroot]# touch etc/shadow
[root@Test02 sysroot]# grep '^root\>' /etc/passwd > etc/passwd
[root@Test02 sysroot]# grep '^root\>' /etc/shadow > etc/shadow
编译dropbear
6.1)在宿主机上编译dropbear
1
2
3
[root@Test02 source]# tar -xf dropbear-2015.67.tar.bz2
[root@Test02 source]# cd dropbear-2015.67
[root@Test02 dropbear-2015.67]# ./configure && make && make install
6.2)移植宿主机上的dropbear程序:dropbear dropbearkey dbclient 至测试机根文件分区磁盘
*复制脚本在第7项中提供
1
2
3
4
5
6
7
8
9
10
11
12
[root@Test02 sysroot]# bash /root/source/copy.sh
Input a command(keyword 'quit' for outworld):>dropbear
copy /usr/local/sbin/dropbear ok
copy /usr/local/sbin/dropbear lib ok
Input a command(keyword 'quit' for outworld):>dropbearkey
copy /usr/local/bin/dropbearkey ok
copy /usr/local/bin/dropbearkey lib ok
Input a command(keyword 'quit' for outworld):>dbclient
copy /usr/local/bin/dbclient ok
copy /usr/local/bin/dbclient lib ok
Input a command(keyword 'quit' for outworld):>quit
[root@Test02 sysroot]#
6.3)生成dropbear提供sshd服务需要的密钥文件
1
2
3
4
[root@Test02 sysroot]# mkdir etc/dropbear
[root@Test02 sysroot]# dropbearkey -t dss -f /mnt/sysroot/etc/dropbear
[root@Test02 sysroot]# dropbearkey -t rsa -s 2048 -f /mnt/sysroot/etc/dropbear
[root@Test02 sysroot]#
6.4)设定dropbear提供的sshd服务在开机后自启动
1
2
3
4
5
[root@Test02 sysroot]# touch etc/rc.d/rc.local
[root@Test02 sysroot]# echo '/usr/local/sbin/dropbear -E'>etc/rc.d/rc.local
[root@Test02 sysroot]# cat etc/rc.d/rc.local
/usr/local/sbin/dropbear -E
[root@Test02 rc.d]# chmod +x rc.local
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@Test02 sysroot]# vim etc/rc.d/rc.sysinit
#!/bin/sh
echo -e "\t Welcome to \033[31;1mPriate Li Home\033[0m"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
mount -n -o remount,rw /dev/sda2 /
/sbin/mdev -s
mkdir /dev/pts
/sbin/ifconfig lo 127.0.0.1 netmask 255.0.0.0 up
/sbin/ifconfig eth0 192.168.100.30 netmask 255.255.255.0 up
[ -r /etc/sysconfig/network ]&&source /etc/sysconfig/network
[ -n $HOSTNAME ]&&/bin/hostname $HOSTNAME || /bin/hostname localhost
mount -a
exec /etc/rc.d/rc.local