网上的资料参差不齐,有懂的没说清楚,有不懂只是在瞎转发。这里呢,本人也不是很懂,但是制作内核rpm包的这条路走通了。
修改内核源码有2种方式打rpm包:
一种是,直接解压内核tar.xz包,修改编辑完成后直接打包覆盖原有的tar.zx包,执行rpmbuild命令构建。另一种是, 解压内核tar.zx包,备份需要修改的源文件,修改后对比源文件生成patch补丁,并在kernel.spec配置中指定补丁文件,执行rpmbuild构建。
第一种方式比较繁琐,第二种更方便,更通用,这里采用第二种方式。
说一下这里的场景,在系统新建一个内核网络模块test_rpm,但是呢,在内核协议栈、tun/tap驱动中又有一些定制化的修改。
1. 先从官网下载kernel的rpm安装包说起:
yum install -y asciidoc audit-libs-devel bash bc binutils binutils-devel bison diffutils elfutils elfutils-devel elfutils-libelf-devel findutils flex gawk gcc gettext gzip hmaccalc hostname java-devel m4 make module-init-tools ncurses-devel net-tools newt-devel numactl-devel openssl patch pciutils-devel perl perl-ExtUtils-Embed pesign python-devel python-docutils redhat-rpm-config rpm-build sh-utils tar xmlto xz zlib-devel
rpm -ivh kernel-3.10.0-1127.el7.src.rpm
tar -xf /root/rpmbuild/SOURCES/linux-3.10.0-1127.el7.tar.xz -C /tmp
cd /tmp/linux-3.10.0-1127.el7
2. 备份要修改的文件,后面有用,后缀可以任意去定制,我这里用了_orig,你可以是.orig,或者别的。
cp include/linux/netdevice.h include/linux/netdevice_orig.h
cp drivers/net/tun.c drivers/net/tun_orig.c
cp net net_orig (在net目录下要修改和添加一批文件,所以可以直接备份net目录)
3. 接下来替换掉要修改的目标文件
mkdir net/test_rpm
这里test_rpm的所有修改文件这里列出:
include/linux/netdevice.h
drivers/net/tun.c
net/core/dev.c、 net/Makefile、 net/Kconfig
net/test_rpm/test.c、 net/test_rpm/test.h、 net/test_rpm/Makefile、 net/test_rpm/Kconfig
4. 使用 diff 命令生成补丁文件
diff -up include/linux/netdevice_orig.h include/linux/netdevice.h >> /tmp/custom1.patch
diff -up drivers/net/tun_orig.c drivers/net/tun.c >> /tmp/custom2.patch
diff -up net_orig net >> /tmp/custom3.patch
然后,cd ~/rpmbuild
手动修改SOURCES: kernel-3.10.0-x86_64.config、 kernel-3.10.0-x86_64-debug.config
分别都添加上一行: CONFIG_TEST=m
这里涉及到内核驱动开发,自己上网修改查一下添加模块以及Makefile和Kconfig的写法
5. 手动修改SPECS: vim kernel.spec
第6行: %define buildid .local 注:%define之间没有空格
第795~797行: 注意这里 -p0 搜索ApplyOptionalPatch 在下面添加下面三行
patch -p0 -F1 -s < $RPM_SOURCE_DIR/custom1.patch
patch -p0 -F1 -s < $RPM_SOURCE_DIR/custom2.patch
patch -p0 -F1 -s < $RPM_SOURCE_DIR/custom3.patch
这里是定制化修改,因为一直报这个之类的错:
“1 out of 1 hunk FAILED -- saving rejects to file net/Makefile.rej”
这种错误一般是运行kernel.spec,内部报的错,这里是应用补丁文件去patch是报的错。
6. 开始制作rpm包 这个过程时间比较长,单核的机器需要一个小时左右
rpmbuild -bb --without kabichk --target=`uname -m` SPECS/kernel.spec
完成后,查看生成的rpm包:ll RPMS/x86_64
kernel-3.10.0-1127.el7.local.x86_64.rpm
kernel-devel-3.10.0-1127.el7.local.x86_64.rpm
kernel-headers-3.10.0-1127.el7.local.x86_64.rpm
kernel-tools-3.10.0-1127.el7.local.x86_64.rpm
kernel-tools-libs-3.10.0-1127.el7.local.x86_64.rpm
kernel-tools-libs-devel-3.10.0-1127.el7.local.x86_64.rpm
7. 安装自己生成的内核rpm包,测试一下:
rpm -ivh RPMS/x86_64/kernel-3.10.0-1127.el7.local.src.rpm
ll /boot/ 必须有这几行:
config-3.10.0-1127.el7.local.x86_64
initramfs-3.10.0-1127.el7.local.x86_64.img
symvers-3.10.0-1127.el7.local.x86_64.gz
System.map-3.10.0-1127.el7.local.x86_64
vmlinuz-3.10.0-1127.el7.local.x86_64
同时 vim /boot/grub2/grub.cfg,会新增对应内核版本的菜单 : 当然这里不用一模一样,具体应该参考个人的机器,其实在这几行的下面会有类似的两个内核版本,因为你的主机至少会有两个内核版本
menuentry 'CentOS Linux (3.10.0-1127.el7.local.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1127.el7.x86_64-advanced-e558a2bf-04c2-4573-9376-8c7ea58f9ae4' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' bcdcab1b-9afa-43b9-86cf-8fbc7567ef9f
else
search --no-floppy --fs-uuid --set=root bcdcab1b-9afa-43b9-86cf-8fbc7567ef9f
fi
linux16 /vmlinuz-3.10.0-1127.el7.local.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto spectre_v2=retpoline rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8
initrd16 /initramfs-3.10.0-1127.el7.local.x86_64.img
}
reboot
8. 这里可以在设置一下系统默认启动内核版本:
grub2-deitenv list //查看当前内核版本
cat /boot/grub2/grub.cfg | grep menuentry
grub2-set-default 'CentOS Linux (3.10.0-1127.el7.local.x86_64) 7 (Core)'