Linux Kernel 编译安装
Linux Kernel 编译安装
1. 什么是Linux Kernel
- Linux内核是一种开源的类Unix操作系统宏内核。实际上就是系统上面的一个文件,这个文件文件包含了硬件的检测程序和驱动模块,负责了整个硬件的驱动,以及各种系统所需要的内核功能,是操作系统的最底层最核心的部分
- 在Linux的启动流程中,当系统读取完BIOS并加载MBR内的启动引导程序后,就加载内核文件到内存中,然后系统依据该文件来检测并驱动各种硬件资源,挂载根目录,调用
$systemd来启动操作系统所需要的服务 - 内核文件一般情况下置于
/boot/目录下,一个Linux系统可以存在多个内核,但是同一时间只能运行一个
2. 什么是Linux Kernel Module
- 为了避免硬件的快速迭代而带来的内核支持不足的问题,Linux Kernel将一些不常用 / 不普遍的类似驱动的东西做成了内核模块,使之可以在系统运行中装载,也可以后期再不更换内核的情况下自行添加
- 一般Module文件都位于
/lib/modules/$(uname -r)/kernel文件目录下面
3. Linux Kernel 目录用途
arch: 与硬件平台相关的项目,大部分与CPU相关,例如架构 / 虚拟化支持block: 与块设备相关的设置数据,块数据一般指大容量储存媒介,还包括是否支持ext3文件系统crypto: 内核支持的加密技术,像md5/md4Documentation: 说明文件,类似于内核附带的官方文档吧drivers: 硬件驱动程序firmware: 比较老的硬件的固件文件fs: 内核所支持的文件系统,像vfat/reiserfs/nfsinclude: 可以让其他程序调用的一些头文件init: 内核的初始化功能,包括挂载与init程序的调用ipc: 定义Linux操作系统内部各程序间的通信kernel: 定义内核的进程、内核状态、线程、进程的调度、进程的信号等lib: 函数库mm: 与内存相关的各项数据,也包括了swap和 虚拟内存net: 与网络相关的各项协议数据,也包括net/ipv4/netfilter等防火墙模块security: 包括SELinux等在内的安全设置sound: 和音效相关的模块virt: 与虚拟化有关的信息,一般是支持KVM虚拟技术
4. 几个重要的内核文件概述
-
.config: 使用make menuconfig命令,经过个性化设置后生成的文件,决定了内核各个功能的编译与否,与编译的方式(编译进入内核还是编译成模块),查看该文件的使用建议使用more命令,因为,这个文件有九千多行

-
vmlinuz&vmlinux:vm是Virtual Memory的缩写,意味这两个东西都是可以引导的内核,Linux支持使用硬盘空间作为虚拟内存vmlinuz: Virtual Memory LINUx gZip = Compressed Linux kernel Executablevmlinuz是可执行的Linux内核,vmlinuz的建立有两种方式- 编译时使用
make zImage创建,zImage的存在是为了兼容小内存设备 - 编译时使用
make bzImage创建,bzimage是压缩的内核镜像,此处的bzImage并非使用bzip2压缩,其bz前缀的含义为big zImage,其与zImage相同,都是使用gzip压缩的
- 编译时使用
bzImage/zImage不单单是压缩文件这么简单,其文件头部都有gzip解压缩代码,所以用户不应该使用gunzip/gzip -dc来解压缩vmlinuz。在内核文件中包含着一个专用的gzip来处理解压缩内核并引导的过程
vmlinux: Virtual Memory LINUX = Non-compressed Linux Kernel Executablevmlinux是 未经压缩的内核,经过特殊压缩后可以变为vmlinuz
-
vmlinux.bin: 该文件除了是可引导的原生二进制文件格式外,与vmlinux相同 -
initrd.img:initrd,img是inttial ramdisk的缩写。initrd一般用于临时性的引导硬件到实际内核vmlinuz能够接管并继续引导的状态。 -
System.map: 该文件是一个特定内核的内核符号表,由nm vmlinux产生并且不相关的符号会被滤除,内核本身可能并不直接使用System.map但是其他程序例如说ps/lsof/klogd等需要使用正确的System.map文件
5. 内核的编译
5.1. 内核的下载
5.1.1. 获取内核文件的渠道
- Linux Kernel有着自己的官方网站,开发人员可以在该网站下载,当然,首页可能并非包含所有Kernel存档,你可以在该存档网址找到所有Linux发布的内核版本
- 由于Linux Kernel的服务器位于国外,所以载国内的用户体验可能不好,甚至无法下载,为此,几大机构建立了Linux Kernel的官方镜像库,定时与官方仓库同步,常用的几个Mirror如下
5.1.2. 将内核文件下载到Linux
-
如果是虚拟机系统的话,一种方式是直接在Linux中下载内核压缩包,另一种就是下载 / 复制该压缩包到宿主机,再通过介质或者
vmtool的方式拷贝到Linux,笔记采用第一种方式记录,欲编译的内核版本号为5.0 -
打开一个
Terminal,键入命令获取内核压缩包,这里使用阿里云的CDN镜像wget https://mirrors.aliyun.com/linux-kernel/v5.x/linux-5.0.tar.gz -
将该内核压缩包文件拷贝复制到
/usr/src/目录下cp ./linux-5.0.tar.gz /usr/src/ -
切换工作目录到
/usr/src/cd /usr/src/ -
解压Linux Kernel压缩包文件
tar xzvf ./linux-5.0.tar.gz -
[可选] 删除该目录下暂时无用的tar压缩包文件
rm -rf ./linux-5.0.tar.gz -
最后,工作文件夹下的文件应显示下述截图的红色划线部分,其余文件目录可能与截图不同

5.2. 内核的配置
-
首先应进入欲编译内核的文件目录下
cd /usr/src/linux-5.0/ -
如果我们并不清楚该内核源码是否经过了编译,产生了目标文件,那么我们首先要将文件还原到最初始的版本
make mrproper -
上一条命令也会清除掉可能存在的配置文件,如果你并非第一次编译,并且不想重新生成配置文件,那么可以退而执行
make clean -
下面要生成欲编译内核的配置文件
.config,这里我使用的是menuconfigmake menuconfig
-
menuconfig的交互还是很简单的,其手册在上方截图 1 区有官方文档- 左右箭头表示对 3 区域的操作
- 上下箭头表示对 2 区域的操作,2 区域的异色条选中行若存在
--->表示当前选中项有子选项可以设置,此时若 3 区域异色条位于select区域,可以回车进入子选项 - 当异色条所在行前部有
[]/<>符号存在时,表明当前项可以选中 / 不选中,空格键切换状态 - 可选项显示为
[*]/<*>时,表示该项编译进内核,如显示为<M>则表示该项作为模块被编译 Esc连续按两次表示从当前菜单退回到上一层- 所有配置选项都设置完毕后,应将 3 区域异色条移动至
Save,保存当前文件到.config,保存成文件之后,就可以退出该界面了
-
我的内核配置选择项
- 选中 :`
Enable loadable module support -> Forced module loading & Force module unloading - 选中 :`
FileSystem->DOS/FAT/NT FileSystems -> NTFS write support - [可选] :
General setup -> Local version - append to kernel release追加字符-fancyking
- 选中 :`
-
前面的操作做完后,如果保存成功,
linux-5.0/下应该如图所示
5.3. 内核文件的编译安装
5.3.0 替换软件安装源 [可选] / [强烈建议]
-
因为Linux默认的官方安装源位于国外,所有有时候下载速度很慢,或者根本连接不上,这里建议更换成国内的镜像软件源
-
各大开源镜像站的 help 页面大都会告诉用户应该如何更改文件来使用户的系统使用该镜像,类似于USTC Mirror,这里省去这一部分,代替为记录一键换源工具
-
下列指令对 Ubuntu 有效,其余系统未经测试,下述语句完成后,会使用阿里的镜像仓库
wget git.io/superupdate.sh && \ chmod +x superupdate.sh && \ bash superupdate.sh aliyun
5.3.1. 简易版内核编译安装(直接替换本机内核)
-
首先,应先安装编译安装内核所需要的依赖,这里我经过实验,Ubuntu 16.04 / 14.04 / 18.04 基本需要安装下述依赖
apt install libc6-dev \ make \ dpkg-dev \ linux-libc-dev \ libssl-dev kernel-package \ libncurses5-dev \ fakeroot \ bc xz-utils \ ca-certificates \ ncurses-dev \ libncurses5-dev \ bison \ flex \ libelf-dev -y --fix-missing && \ apt upgrade -y && \ apt autoclean -y && \ apt clean -y && \ apt autoremove --purge -y -
执行make,使生成内核模块 /
vmlinuz/initrd.img/System.map文件make -j 4执行上述语句时应注意,
-j选项的意思是,允许参与编译的内核数目,该选项不应该大于虚拟机拥有的内核数目,如果不使用-j选项意味单内核编译,自然速度会比四核慢些。缺省值为不限制,如果资源紧张有可能出现死机 / 负载极高的情况,所以尽量填写的话就正确填写,否则可能像下面一样
该语句执行成功的标志是在没有
Error的情况下结束运行,类似显示下述信息
-
执行make modules_install 和 make install
make modules_install -j 4 make install -j 4这一步操作会复制模块文件到
/lib/modules/目录下,复制config/vmlinuxz/initrd.img/System.map文件到/boot/目录,并且会自动更新grub引导项语句执行成功的标志是在没有
Error的情况下结束运行,类似显示下述信息下图为
modules_install的完成状态图
下图为
install的完成状态图
-
执行完上述命令之后,grub应该会自动更新的,所以可以重启验证一下,我的显示如下

-
如果在重启过程中遇到了下图所示的报错,可以临时性的增加自己的内存,当引导进入系统之后,再把内存降下来也没事

-
至此,该方式的内存编译安装完成
5.3.2. 打包替换
- 先挖坑,以后再写