第24章 Linux核心编译与管理

第24章 Linux核心编译与管理

24.1 编译前的任务:认识核心与取得核心原始码

24.1.1 什么是核心(Kernel)

  • Kernel
    其实核心就是系统上面的一个文件而已,这个文件包含了驱动主机各项硬件的侦测程序与驱动模块。
  • 核心模块的用途
    将一些不常用的类似驱动程序的咚咚独立出核心,编译成为模块,然后,核心可以在系统正常运作的过程当中加载这个模块到核心的支持。如此一来,我在不需要更动核心的前提之下,只要编译出适当的核心模块,并且加载他,呵呵!我的Linux就可以使用这个硬件啦!简单又方便!
    那我的模块放在哪里啊?可恶!怎么会问这个傻问题呢?当然一定要知道的啦!就是/lib/modules/$(uname -r)/kernel/当中啦!
  • 自制核心 - 核心编译
  • 关于驱动程序 - 是厂商的责任还是核心的责任?
    在【驱动程序开发】的工作上面来说,应该是属于硬件发展厂商的问题。

24.1.2 更新核心的目的

  所有目前核心有支持的东西都给他编译进去我的核心中,那就可以支持目前所有的硬件与可执行的工作啦!

  • Linux核心特色,与默认核心对终端用户的角色
  • 核心编译的可能目的
    • 新功能的需求
    • 原本核心太过臃肿
    • 与硬件搭配的稳定性
    • 其他需求(如嵌入式系统)

24.1.4 核心原始码的取得方式

24.3.2 实际安装模块

  安装模块前有个地方得要特别强调喔!我们知道模块是放置到/lib/modules/$(uname -r)目录下的,那如果同一个版本的模块被反复编译后来安装时,会不会产生冲突呢?举例来说,鸟哥这个3.10.89的版本每一次编译完成且安装妥当后,发现有个小细节想要重新处理,因此又重新编译过一次,那两个版本一模一样时,模块放置的目录会一样,此时就会产生冲突了!如何是好?有两个解决方法啦:

  • 先将旧模块目录更名,然后才安装核心模块到目标目录去
  • 在make menuconfig时,那个General setup内的Local version修改成新的名称。

  鸟哥建议第二个方式,因为如此一来,你的模块放置的目录名称就不会相同,这样就能略过上述的目录同名问题啰!好,那么如何安装模块到正确的目标目录呢?很简单,同样使用make的功能即可:

make modules_install
ll /lib/modules/

  看到否,最终会在/lib/modules底下建立起你这个核心的相关模块哦!不错吧,模块这样就已经处理妥当啰~接下来,就是准备要进行核心的安装了!

24.3.3 开始安装新核心 与多重核心选单(grub)

  • 移动核心到/boot且保留旧核心文件
[root@study linux-3.10.89]# cp arch/x86/boot/bzImage /boot/vmlinuz-3.10.89vbird
[root@study linux-3.10.89]# cp .config /boot/config-3.10.89vbird
[root@study linux-3.10.89]# chmod a+x /boot/config-3.10.89vbird
[root@study linux-3.10.89]# cp System.map /boot/System.map-3.10.89vbird
[root@study linux-3.10.89]# gzip -c Module.symvers > /boot/symvers-3.10.89vbird.gz
[root@study linux-3.10.89]# restorecon -Rv /boot
  • 建立相对应的Initial Ram Disk(initrd)
    刚刚SATA磁盘支持的功能并没有直接编译到核心去,所以当然要使用initramfs来加载才行!使用如下的方法来建立initramfs吧!记得搭配正确的核心版本哦!
    dracut -v /boot/initramfs-3.10.89vbird.img 3.10.89vbird

  • 编辑开机选单
    接下来就直接使用grub2-mkconfig来处理你的grub2开机选单设定即可!
    grub2-mkconfig -o /boot/grub2/grub.cfg
    因为预设较新版本的核心会放在最前面成为默认的开机选单项目,所以你得要确认上述的结果中,第一个被发现的核心为你刚刚编译好的核心文件才对哦!

24.4 额外(单一)核心模块编译

  我们现在知道核心所支持的功能当中,有直接编译到核心内部的,也有使用外挂模块的,外挂模块可以简单的想成就是驱动程序啦!那么也知道这些核心模块依据不同的版本,被分别放置到/lib/modules/$(uname -r)/kernel/目录中,各个硬件的驱动程序则是放置到/lib/modules/$(uname -r)/kernel/drivers/当中!换个角度再来思考一下,如果刚刚我自己编译的数据中,有些驱动忘记编译成为模块了,那是否需要重新进行上述的所有动作?又如果我想要使用硬件厂商释出的新驱动程序,那该如何是好?

24.4.1 编译前注意事项

  在2.6版本以后,核心使用比较有趣的方法来设计他的原始码放置目录,那就是以 /lib/modules/$(uname -r)/build 及 /lib/modules/$(uname -r)/source这两个连结档来指向正确的核心原始码放置目录。
  由于核心模块的编译其实与核心原本的原始码有点关系的,因此如果你需要重新编译模块时,那除了make,gcc等主要的编译软件工具外,你还需要的就是kernel-devel这个软件!记得一定要安装哦!而如果你想要在预设的核心下新增模块的话,那么就得要找到kernel的SRPM文件了!将该文件给他安装,并且取得source code后,才能够顺利的编译哦!

24.4.2 单一模块编译

  • 如果我的默认核心忘记加入某个功能,而且该功能可以编译成为模块,不过,预设核心却也没有将该功能编译成为模块,害我不能使用时,该如何是好?
  • 如果Linux核心原始码并没有某个硬件的驱动程序(module),但是开发该硬件的厂商有提供给Linux使用的驱动程序原始码,那么我以该如何将该功能编译进核心模块呢?

  很有趣对吧!上面那两种情况的模块编译行为是不太一样的,不过,都是需要make,gcc以及核心所提供的include头文件与函式库等等。

  • 硬件开发商提供的额外模块
    如果你的硬件开发商有提供驱动程序的话,那么真的很好解决,直接下载该原始码,重新编译,将他放置到核心模块该放置的地方后就能够直接使用了!举个例子来说,鸟哥在2014年底帮厂商制作一个服务器的环境时,发现对方喜欢使用的磁盘阵列卡(RAID)当时并没有被Linux核心所支持,所以得要帮厂商针对该磁盘阵列卡来编译成为模块啰!处理的方式,当然就是使用磁盘阵列卡官网提供的驱动程序来编译啰!
      鸟哥假设你将下载的文件放置到/root/raidcard目录内哦!
# 1. 将文件解压缩并且开始编译:
cd /root/raidcard
ll
tar -zxvf RR64xl_Linux_Src_vl.3.9_15_03_07.tar.gz
cd rr64xl-linux-src-v1.3.9/product/rr64xl/linux/
ll
make

# 2. 将模块放置到正确的位置去
cp rr6401.ko /lib/modules/3.10.89vbird/kernel/drivers/scsi/
depmod -a 
grep rr640 /lib/modules/3.10.89vbird/modules.dep

modprobe rr6401

#3. 若开机过程中就得要加载此模块,则需要将模块放入initramfs才行哦
dracut --force -v -add-drivers rr6401 > /boot/initramfs-3.10.89vbird.img 3.10.89vbird
lsinitrd /boot/initramfs-3.10.89vbird.img | grep rr640

  需要提醒你的是,当自行编译模块时,若你的核心有更新时,则你必须要重新编译该模块一次,重复上面的步骤才行!

  • 利用旧有的核心原始码进行编译
    如果你后来发现忘记加入某个模块功能了,那该如何是好?我们先到目前的核心原始码所在目录下达make menuconfig,然后将NTFS的选项设定成为模块,之后直接下达:
    make fs/ntfs/
      那么ntfs的模块(ntfs.ko)就会自动的被编译出来了!然后将该模块复制到/lib/modules/3.10.89vbird/kernel/fs/ntfs/目录下,再执行depmod -a,呵呵就可以在原来的核心底下新增某个想要加入的模块功能啰_

24.5 以最新核心版本编译CentOS 7.x的核心

  如果你跟鸟哥一样,曾经为了某些缘故需要最新的4.x.y的核心版本来实作某些特定的功能时,那该如何是好?没办法,只好使用最新的核心来编译啊!你可以依照上面的程序来一个一个处理,没有问题~不过,你也可以根据EPRepo网站提供的SRPM来重新编译打包哦!当然你可以直接使用ELRepo提供的CentOS 7.x专属的核心来直接安装。
  底下我们使用ELRepo网站提供的SRPM文件来实作核心编译。而要这么重新编译的原因是,鸟哥需要将VFIO的VGA直接支持的核心功能打开!因此整个程序会变成类似这样:

  1. 先从ELRepo网站下载不含原始码的SRPM文件,并且安装该文件
  2. 从www.kernel.org网站下载满足ELRepo网站所需要的核心版本来处理
  3. 修改核心功能
  4. 透过SRPM的rpmbuild重新编译打包核心

  就让我们来测试一下啰!(注意,鸟哥使用的是2015/10/20当下最新的4.2.3这一版的核心。由于核心版本的升级太快,因此在你实作的时间,可能已经有更新的核心版本了。此时你应该要前往ELRepo查阅最新的SRPM之后,再决定你想使用的版本喔!)

1. 先下载ELRepo上面的SRPM文件!同时安装它:
wget http://elrepo.org/linux/kernel/el7/SRPMS/kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm
rpm -ivh kernel-ml-4.2.3-1.el7.elrepo.nosrc.rpm

2. 根据上述的文件,下载正确的核心原始码
wget https://cdn.kernel.org/pub/linux/v4.x/linux-4.2.3.tar.xz
ll -tr

3. 修改核心的功能设定
# 大约在5623行找到底下这一行,并在底下新增一行设定值
# CONFIG_VFIO_PCI_VGA is not set
CONFIG_VFIO_PCI_VGA=y

cd ../SPECS
vim kernel-ml-4.2.spec
# 大概在145左右找到底下这一行:
Source0: ftp://ftp.kernel.org/pub/linux/kernel/v4.x/linux-%{LKAver}.tar.xz
将它改成如下的模样:
Source0: linux-%{LKAver}.tar.xz

4. 开始编译并打包
rpmbuild -bb kernel-ml-4.2.spec
# 接下来会有很长的一段时间在进行编译行为,鸟哥的机器曾经跑过两个小时左右才编译完!

接下来你也不需要像手动安装核心一样,得要一个一个项目移动到正确的位置去,只要使用yum install新的核心版本,就会有4.2.3版的核心在你的CentOS 7.x当中了耶!相当神奇!
yum install /root/rpmbuild/RPMS/x86_64/kernel-ml-4.2.3-1.el7.centos.x86_64.rpm
reboot

uname -a
这样就让我们的CentOS 7.x具有最新的核心啰!与核心官网相同的版本咧~够帅气吧!
posted @ 2023-07-31 10:50  Evan-whc  阅读(21)  评论(0编辑  收藏  举报