Linux内核编译
编译前的准备
- 首先,最最重要的一点,一定要拍摄快照,一定要拍摄快照,一定要拍摄快照(重要的事情说三遍)。
- 其次,编译前一定要留好足够的空间,否则可能会出现“磁盘空间不足”的错误。
- 进入Linux官网https://www.kernel.org/下载对应版本的内核。我这里下载的是6.0.7最新版的内核。
解压
解压缩到/usr/src/目录下。
sudo tar xvf ./linux-6.0.7.tar.xz -C /usr/src/
添加系统调用(非必需)
分配系统调用号
Linux系统调用号都在arch/x86/entry/syscalls/syscall_64.tbl
中,编辑此文件,添加自己喜欢的系统调用号。
声明系统调用
在include/linux/syscalls.h
中添加函数声明。
添加系统函数定义
在kernel/sys.c
中末尾添加如下代码。
注意:SYSCALL_DEFINE0是接收0个参数的系统调用宏。这里仅仅定义了一个简单的打印函数,这里使用了内核态printk()
函数。
至此,系统调用添加便大功告成了。
内核的配置与编译
第一次操作(Failure:磁盘空间不足)
配置内核
至此,我们迈出了一小步。现在要开始繁杂的内核配置工作了。
在/usr/src/linux-6.0.7
目录下,图形化配置内核选项。
make menuconfig
这里出师不利,一上来就报错了。不过,不要怕错误,我们一步步解决。
缺乏对应依赖包,安装即可。
sudo apt install libncurses-dev
继续配置,又报了一个错。
依然是缺乏对应依赖包,安装即可。
sudo apt-get install flex
我们继续,结果又报错了。
依然是缺乏依赖包,安装即可。
sudo apt-get install bison -y
终于到了图形化配置了,感觉好难啊。
这一步一般不需要怎么配置,直接保存退出即可。当然,如果你想添加一些其它必需配置可以直接修改配置项。
一般而言,配置选项都是保存在.config
中的,如果忘记勾选了一些选项,可以手动修改该文件配置。
编译内核
终于到了编译内核这一步了。提醒一下,这里不同的机子需要的时间也不尽相同,但是慢是肯定的了。我们可以做一些其它的事情,然后静静的等待编译完成就可以了。
make
当然,如果你嫌此过程太慢的话,可以指定-j
选项。
make -j4 # 表示最多允许make同时以4条编译命令执行。
唉。。。又报错了。
这里翻看相关博客,发现还是缺乏相关依赖项,安装即可。
sudo apt-get install libelf-dev
继续编译,大约5~6分钟了吧。正当笔者想安心喝口茶时,结果又报错了。
解决过程,这里直接编辑.config
文件即可。
将CONFIG_SYSTEM_TRUSTED_KEYS
等号右侧字符串置空即可。如上图所示。
Tips:vim定位字符串
在命令行模式下,输入/
,然后输入要定位的字符串就可定位到我们需要的位置。比如,上述选项定位
/CONFIG_SYSTEM_TRUSTED_KEYS
刚解决完上一个问题,又报错了
这里依然是编辑.config
文件。
同样的,将CONFIG_SYSTEM_REVOCATION_KEYS
右侧字符串置空。
注意,此处继续编译需要执行make clean
,清除掉已编译内容,防止对之后产生影响,然后再继续编译。
make clean
make
笔者电脑太拉了,编译了3个小时了,还没有编译完。
不过,编译过程中出现了一个警告消息。
解决办法:
主要是因为内核选项中设置了堆栈大小报警,其默认为1024bytes。
若我们将其大小修改为4096bytes,则可消除此报警信息。即在配置内核选项时,修改warn for stack frames larger than
的值为4096bytes,然后重新编译。
终于,在编译了5个小时后,我失败了。
主要是因为磁盘空间不足,啊这里真是无语了,笔者本以为自己的虚拟机有50GB内存的,提示空间不足时,还挺震惊的,然后我查看虚拟机的内存,才30GB。真的犹如晴天霹雳,完蛋了。
所以接下来,我们需要进行磁盘扩充,这里详细方法请参考笔者的另一篇文章Ubuntu磁盘扩展
第二次操作(Success)
配置内核
具体配置及错误参考第一次操作即可。
不过,这里为了解决第一次编译出现的警告问题,还需要进行一个简单的图形化配置。具体操作如下:
至此,图形化配置结束。
编译内核
详细操作与第一次编译相同,直接编译即可。
make -j4
再次经历了将近5个小时的漫长等待后,笔者终于编译成功了。
可能有读者会问,这不是还在编译中吗,怎么已经能说成功了呢?
这是因为我们采取了多线程编译,通过提供-j4
选项,指定4个线程。此时,虽然还在进行编译,但是关键镜像bzImage已经压缩成功了。我们现在离编译成功只有一步之遥,所以不用再提心吊胆了,只需静静地等待后续收尾工作完成了。
终于,编译了大致6个小时后,编译完成了。
这里我们主要关注的是vmlinux
,这是编译提取出来的原始模块,也是内核编译的核心文件。
Tips:编译所需空间测算
编译前:
编译后:
可以测算,我们编译前后一共用了20G内存。所以,编译前一定要预留至少20G的空间。
编译和安装模块
make modules
make modules_install
此时,我们依然可以提供-j
选项来进行多线程处理。但其实并没必要,因为编译和安装模块本身就很快。
安装内核
make install
安装成功。
重启
终于到了检验结果的时候了,真是激动的心,颤抖的手啊!
reboot
重启后,我们能看到如下界面,具体就是选择使用的内核。
这里我们选择第二个。
然后,这里我们选择第一个,也就是我们新编译的内核。
回车就可正常启动了。
安装成功,完结撒花!!!
在重启过程中报了一个错误。具体如下:
解决方法:
就是说内存不够了,内存溢出了,扩大内存就行了。这里笔者将内存扩大到了4G
。
检验系统调用
不知道大家是否还记得,我们上述定义的系统调用。我就当大家不记得了,再粘贴一遍吧。
这里,我们通过一个简单程序进行检验。
#include <stdio.h>
#include <unistd.h>
int main()
{
syscall(714); // 调用我们自己定义的系统调用
return 0;
}
编译并运行。
gcc demo.c -o demo
./demo
运行完了,似乎并没什么用。
但是,不知你是否忘了,我们使用的是内核态函数printk
,所以是无法直接打印到屏幕上。这里我们使用dmesg
命令查看。
dmesg # 显示内核启动信息
可以看到,系统调用成功。
总结
通过对内核的编译以及安装,感觉整个人都变得佛系了。不过,在这个过程中,笔者也收获了很多。
Tips:这篇文章花了笔者将近两天时间,写文章真实不容易啊!
参考文献:
【1】https://blog.csdn.net/qq_36393978/article/details/118225531
【2】https://blog.csdn.net/m0_48958478/article/details/121620449
【3】https://blog.csdn.net/mantis_1984/article/details/32135989
【4】https://blog.csdn.net/Hackeryuan/article/details/103917445