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 / md4
  • Documentation : 说明文件,类似于内核附带的官方文档吧
  • drivers : 硬件驱动程序
  • firmware : 比较老的硬件的固件文件
  • fs : 内核所支持的文件系统,像 vfat / reiserfs / nfs
  • include : 可以让其他程序调用的一些头文件
  • init : 内核的初始化功能,包括挂载与 init 程序的调用
  • ipc : 定义Linux操作系统内部各程序间的通信
  • kernel : 定义内核的进程、内核状态、线程、进程的调度、进程的信号等
  • lib : 函数库
  • mm : 与内存相关的各项数据,也包括了 swap 和 虚拟内存
  • net : 与网络相关的各项协议数据,也包括 net / ipv4 / netfilter 等防火墙模块
  • security : 包括 SELinux 等在内的安全设置
  • sound : 和音效相关的模块
  • virt : 与虚拟化有关的信息,一般是支持 KVM 虚拟技术

4. 几个重要的内核文件概述

  • .config : 使用 make menuconfig 命令,经过个性化设置后生成的文件,决定了内核各个功能的编译与否,与编译的方式(编译进入内核还是编译成模块),查看该文件的使用建议使用 more 命令,因为,这个文件有九千多行

    Snipaste_2019-05-17_21-45-54.png

    Snipaste_2019-05-17_21-47-00.png

  • vmlinuz & vmlinux : vmVirtual Memory 的缩写,意味这两个东西都是可以引导的内核,Linux支持使用硬盘空间作为虚拟内存

    • vmlinuz : Virtual Memory LINUx gZip = Compressed Linux kernel Executable
      • vmlinuz 是可执行的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 Executable
      • vmlinux 是 未经压缩的内核,经过特殊压缩后可以变为 vmlinuz
  • vmlinux.bin : 该文件除了是可引导的原生二进制文件格式外,与 vmlinux 相同

  • initrd.img : initrd,imginttial ramdisk 的缩写。 initrd 一般用于临时性的引导硬件到实际内核 vmlinuz 能够接管并继续引导的状态。

  • System.map : 该文件是一个特定内核的内核符号表,由 nm vmlinux 产生并且不相关的符号会被滤除,内核本身可能并不直接使用 System.map 但是其他程序例如说 ps / lsof / klogd 等需要使用正确的 System.map 文件

  • What is the difference between the following kernel Makefile terms: vmLinux, vmlinuz, vmlinux.bin, zimage & bzimage?

  • Anatomy of the initrd and vmlinuz

5. 内核的编译

5.1. 内核的下载

5.1.1. 获取内核文件的渠道

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,这里我使用的是 menuconfig

    make 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 的情况下结束运行,类似显示下述信息

    ELs8tf.png

  • 执行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 的完成状态图

    ELsbge.png

    下图为 install 的完成状态图

  • 执行完上述命令之后,grub应该会自动更新的,所以可以重启验证一下,我的显示如下

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

  • 至此,该方式的内存编译安装完成

5.3.2. 打包替换

  • 先挖坑,以后再写

标签: Linux, Kernel

添加新评论