前言:为什么要做这个启动盘,因为内核编译是很危险的,中间出了错系统则直接崩溃,然后就无法开机了,你将看到一个_在你的左上角闪烁。知道启动盘可以帮你从外置设备启动系统,能启动系统才能恢复系统。
1.编译前准备
一个可用的大于8G的USB启动盘,格式化为ext3、ext4或VFAT格式。
下载一个镜像文件,下文假设为ubuntu-16.04-64.iso。
一台可以使用的且装有Linux系统的主机(最好装有Centos或Ubuntu),并且具有root权限。
2.安装引导程序
我的u盘只有一个分区,且为/dev/sdb1(以自己的为准。通过lsblk -l 查看)。
syslinux /dev/sdb1
3.创建临时挂载点
为ubuntu-16.04-64.iso和USB存储设备创建挂载点:
mkdir /mnt/isoboot/ /mnt/diskboot
4.挂载ubuntu-16.04-64.iso
-o loop 选项用于创建一个伪设备,让他像设备块一样工作,此时这个目录可以看成一个块设备,如果不理解就可以看成插了一个U盘,里面有你烧录的系统。
mount -o loop ubuntu-16.04-64.iso /mnt/isoboot
5.挂载USB存储设备
mount /dev/sdb1 /mnt/diskboot
6.把镜像中isolinux文件复制到U盘
cp -r /mnt/isoboot/isolinux/* /mnt/diskboot
7.将镜像里的isolinux.cfg复制到u盘
grep -v local的意思是排除保护local的字段:
grep -v local /mnt/isoboot/isolinux/isolinux.cfg > /mnt/diskboot/syslinux.cfg
8.卸载镜像和u盘挂载点
完成以上步骤后执行:
umount /mnt/isoboot /mnt/diskboot
9.重启系统,插上USB启动盘,用USB启动盘启动系统
如果没有从U盘启动,可能需要进入bios界面调整启动顺序,把U盘调整为第一顺序,尝试在开机后迅速按F2、F10、F12(主机型号不同则不同)。
下载、配置并构建内核
配置内核前检查自己的U盘是否在有足够多的空间,最好留存4G以上的空间。
1.下载内核
官网下有http和git两种下载方式,国内用户使用http下载较快,git更加官方,而且里面注明了内核的作者是谁,你可以下载到托瓦茨的内核。
HTTP https://www.kernel.org/pub/GIT https://git.kernel.org/ https://kernel.ubuntu.com/
使用http下载的读者点进去后进入linux目录,再进入kernel目录,再选择版本。
以4.0x为例:https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/
下载方式,wget:
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.0.5.tar.gz
下面有.gzip格式的和.bzip2格式的tar包,.gzip格式的使用命令(xyz代表版本号):
tar xvjf linux-x.y.z.tar.bz2
.zip格式:
tar xvzf linux-x.y.z.tar.gz
2.安装软件依赖
在编译之前,需要在你的操作机上安装一些软件。
build-essential用于在x86_64或arm64系统上编译内核,如果你是armhr(32位的arm架构),可能下面的内容不适合你。
- 安装最新版本的gcc。
- 安装ncurses开发包。
- 还有其他用于交叉编译的软件。
- 安装ncurse-dev,运行make menuconfig时需要用到。
apt-get update && apt-get upgrade
apt-get install build-essential
apt-get install build-essential gcc
apt-get install libncurses5-dev
apt-get install binutils-multiarch
apt-get install alien
apt-get install ncurses-dev
3.解压刚才下载的内核包并进入到目录下
4.在该目录下执行命令:make menuconfig
以下选项根据需求勾选,新手不要随意乱动配置项,安装默认配置就可以了,保存后退出。
5.编译内核
输入命令 -j 5代表开5个进程同时编译,速度比直接运行make要快很多。但是前提是你的CPU是多核多进程的,我的CPU4核,但是我写的5,意思是超频编译,实际上和4没什么区别,因为硬件条件摆在那。
编译需要至少半个小时,耐心等待。
make -j 5
十.安装和启动内核
编译完后,可以安装内核了。首先确保你为当前系统的重要数据做了备份。此外,需要把/boot下的内容复制到一个格式为FAT32的外部存储媒介上。(如u盘,格式化的方法请百度)
1.安装驱动程序
在内核的目录下执行,这个命令会把所有模块复制到当前的/lib/modules下对应的内核版本的子目录中:
make modules_install
2.安装内核
这条命令将执行/sbin/installkernel文件,新内核会被复制到/boot/vmlinuz-{version},version为当前内核的版本号。实际上是一个软连接,链接到真实内核,如果/boot/vmlinuz-{version}存在,将会被覆盖并链接到新内核。旧内核会被保存为/boot/vmlinuz.old。
make install
3.接下来将内核复制到/boot目录
你下载什么版本的就以什么结尾 vmlinuz-{version}。
cp -v arch/x86/boot/bzImage /boot/vmlinuz-4.0.5
4.初始化RAM盘
RAM-随机存取存储器(random access memory)。
- 计算机和手机中一般叫做(运行)内存。
- 高速存取,读写时间相等,且与地址无关,如计算机内存等。
- 通常用来存放操作系统,各种正在运行的软件、输入和输出数据、中间结果及与外存交换信息等。
mkinitramfs -o /boot/initrd.img /lib/modules/4.0.5
5.接下来复制System.map
该文件包含了一系列内核符号和对应地址:
cp System.map /boot/System.map-4.0.5
6.创建符号链接
使System.map指向你新的内核map:
ln -sf /boot/System.map-4.0.5 /boot/System.map
7.重启
如果你以上的步骤没有错,就可以使用新的内核了,如果重启失败,就需要用第一步准备的u启来引导启动,并且还原之前的配置,如果你备份了/boot目录,直接覆盖就可以恢复。
重启成功输入命令查看系统内核版本:
uname -a
十一.测试和调试内核
1.使用Netconsole配置调试用控制台
如果我们想捕捉内核崩溃事件,可一旦系统被重新启动,由于没有创建该事件的日志,那么要捕获它就变得相当困难。我们可以使用Netconsole来解决这个问题。Netconsole是一个内核模块,它通过UDP协议记录内核消息。当不能记录到本地磁盘时,它可帮助调试问题。
在配置Netconsole之前,我们需要知道UDP数据包将被发送到的系统的MAC地址。该系统被称为接收方,可以与本机处于相同子网或者不同的子网。这两种情况描述如下:
第一种情况:接收方与本机在同一子网
使用ping 和arp命令,假设我的接受方为192.168.2.29。
第二种情况:不在同一子网
netstart -rn查看默认网关,图中为192.168.1.1,然后arp -n 192.168.1.1即可。网关就是我们要的MAC地址。
2.更改启动时的内核选项
如果你正在使用Grub作为穷引导程序,它会默认启动内核的'quiet splash'选项,意思是闪屏,不显示启动过程。
先做备份,任何操作前做备份操作总没错:
cp /etc/default/grub /etc/defautl/grub.backup
vim /etc/default/grub
找到GRUB_CMDLINE_LINUX_DEFAULT="quietsplash"这一行,将该行替换为GRUB_CMDLINE_LINUX_DEFAULT="debugignore_loglevel"。
3.更新grub
update-grub
4.初始化Netconsole
将Netconsole模块添加到/etc/modules中,使它能在启动时被加载:
sh -c 'echo netconsole' >> /etc/modules
5.配置Netconosle模块选项
假设网卡为本地eth0,本地ip为192.168.1.11,网关为192.168.1.1(如果不在同一网段),接受方为192.168.2.29,刚才我们已经拿到了接受方的mac地址,<LOCAL_PORT>和<REMOTE_PORT>(本地和对方)的端口都是6666。
格式:netconsole=<LOCAL_PORT>@<SENDER_IP_ADDRESS>/<SENDER_INTERFACE>,<REMOTE_PORT>@<RECEIVER_IP_ADDRESS>/<SETP_1_MAC_ADDRESS>。
#接受方与发送方不在同一网段,发送者网关写本地IP
sh -c 'echo options netconsole netconsole=6666@192.168.1.1/eth0,6666@192.168.2.29/ba:54:fc:df:f2:f0 > /etc/modprobe.d/netconsole.conf'
#接受方与发送方在同一网段,发送者IP写本地IP
sh -c 'echo options netconsole netconsole=6666@192.168.1.11/eth0,6666@192.168.1.29/ba:54:fc:df:f2:f0 > /etc/modprobe.d/netconsole.conf'
6.设置接受方设置
假设接受方,也就是用于监控发送方的主机ip为192.168.2.29,执行以下命令:
netcat -l -u 192.168.2.29 6666 | tee ~/netconsole.log
#也可以不带ip
netcat -l -u 6666 | tee ~/netconsole.log
#由于系统版本不同,上面命令报错则将-u改为-p
netcat -l -p 6666 | tee ~/netconsole.log
7.保持上面命令保持运行,重新开一个终端
输入命令,这样就可以监控内核的崩溃信息了。也可以查看~/netconsole.log。
dmesg | grep netcon