部门已经有固定下来的内核编译方式。迁出完整代码后,加载环境变量文件,直接make即可重新编译内核。修改了某个模块,直接到模块目录下make即可生成模块,很方便。最近想尝试在centos下进行内核开发,查阅了几个centos内核编译wiki说明。感觉比较零散,于是整理出来方便后续查阅和分享。
下载内核源码
$ uname -r
3.10.0-514.26.2.el7.x86_64
有两种方式可以下载centos与当前内核版本一致的源码:
方式1:使用yumdownloader自动下载
$ sudo yum install yum-utils
$ sudo yumdownloader --source kernel
kernel-3.10.0-514.26.2.el7.src.rpm
要注意的是kernel源码下载速度可能很慢,需要挂VPN下载,否则可能会下载失败。
方式2:手工从镜像网站下载
由于软件源镜像站点只保留二进制软件包,所以我们要去centos软件包归档站点“http://vault.centos.org”去下载内核源码。下载地址:http://vault.centos.org/7.3.1611/updates/Source/SPackages/kernel-3.10.0-514.26.2.el7.src.rpm。
编译内核源码
注意:官方强烈建议不要以root身份编译内核源码。主要原因是编译过程中可能有对系统文件的修改操作,如果用root编译就可能在你不知情的情况下直接修改了。用普通用户编译过程中,要是有对系统文件的修改,会因权限不足而报错。详见参考“[5] Building Source RPM as non-root under CentOS ”。
- 以普通用户创建编译rpm所需的基础目录结构
$ mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
$ echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros
- 安装编译内核所需软件包
$ sudo yum install kernel-devel
$ sudo yum install rpm-build redhat-rpm-config asciidoc hmaccalc perl-ExtUtils-Embed pesign xmlto
$ sudo yum install audit-libs-devel binutils-devel elfutils-devel elfutils-libelf-devel
$ sudo yum install ncurses-devel newt-devel numactl-devel pciutils-devel python-devel zlib-devel
- 安装内核源码
$ rpm -i kernel-3.10.0-514.26.2.el7.src.rpm 2>&1 | grep -v exist
$ cd ~/rpmbuild/SPECS
$ rpmbuild -bp --target=$(uname -m) kernel.spec
现在可以在“~/rpmbuild/BUILD/kernel*/linux*”看到完整的内核源代码了。
- 内核编译设置
$ cd ~/rpmbuild/BUILD/kernel-*/linux-*/
$ cp /boot/config-`uname -r` .config
$ cp /usr/src/kernels/`uname -r`/Module.symvers .
$ cp /usr/src/kernels/`uname -r`/System.map .
$ cp /usr/src/kernels/`uname -r`/vmlinux.id .
这里拷贝了当前内核的配置到源码目录。因为只是要编译自己的内核模块,所以直接复用当前内核的配置。避免了重新编译整个内核,以及内核版本校验导致新模块加载错误的问题。
$ make prepare
$ make modules_prepare
- 编译新增模块
$ cd ~/rpmbuild/BUILD/kernel-*/linux-*/
$ mkdir modules
- 增加加载/移除时会打印提示信息的hello模块
hello/hello.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
static int hello_init(void)
{
printk(KERN_ERR "Module init: Hello linux kernel.\n");
return (0);
}
static void hello_exit(void)
{
printk(KERN_ERR "Module exit: Bye-bye linux kernel.\n");
}
module_init(hello_init);
module_exit(hello_exit);
hello/Makefile
obj-m += hello.o
all:
make -C $(PWD) M=$(PWD) modules
clean:
make -C $(PWD) M=$(PWD) clean
$ make M=modules/hello
$ sudo cp modules/hello/hello.ko /lib/modules/`uname -r`/extra
- 新模块加载/移除
$ cd /lib/modules/`uname -r`/extra
$ sudo insmod hello.ko
$ sudo rmmod hello
$ tail -f /var/log/messages
“
* localhost kernel: Module init: Hello linux kernel.
* localhost kernel: Module exit: Bye-bye linux kernel.
”
messages打印出了模块加载/移除时的提示信息,新增模块工作正常。
参考
[1] SystemTap on CentOS,https://sourceware.org/systemtap/wiki/SystemTapOnCentOS
[2] 我需要内核的源代码,https://wiki.centos.org/zh/HowTos/I_need_the_Kernel_Source
[3] 我需要创建一个自设的内核,https://wiki.centos.org/zh/HowTos/Custom_Kernel
[4] 创建你自己的内核模块,https://wiki.centos.org/zh/HowTos/BuildingKernelModules
[5] Building Source RPM as non-root under CentOS,http://www.owlriver.com/tips/non-root/
修订记录
2017-11-05 PM:从网易博客迁移至简书;
2017-07-16 PM:初稿;
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
网友评论