实验环境
- Ubuntu 20.04 LTS
- VMware Workstation Pro 16
- Linux Kernel 5.10.2
存储空间至少留55GB,我第一次做就因为空间不够编译失败,最后编译完系统文件夹大小是51GB
更换国内源
先备份一下趴,养成良好习惯
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
用自己喜欢的编辑器打开
sudo gedit /etc/apt/sources.list
接下来,找到镜像源复制进去。这里一定一定要按照自己的系统版本去选择,尤其是新版本的同学们,不然可能后面install会出现各种版本、依赖、索引的问题。
这是一个大坑,很多教程都是直接给一大段让大家去复制,也不说是什么版本的,可能作者自己也没搞清楚也是复制来的。
建议去清华镜像站选择对应版本,以下给出的是20.04 LTS。
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
最后记得更新一下
sudo apt-get update && sudo apt-get upgrade
安装编译内核所需依赖
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install libc6-dev
sudo apt-get install libelf-dev
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install libidn11-dev libidn11
sudo apt-get install zlibc minizip
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install pkg-config
这一步比较容易出问题,我在做的时候遇到了各种依赖无法安装的报错,如果您第一步更换源听从了我的建议,这里应该一遍过,会少走很多弯路。如果依旧出现报错,我提供几种方法:
- 使用aptitude安装
sudo apt-get install aptitude
sudo aptitude install XXX
- 使用-f
sudo apt-get -f install XXX
- 读报错,缺什么装什么,多了什么卸载什么。反正我段位低了,看不太懂
获取内核源码
去官网下载内核源码。我这里下载的是当前最新稳定版,5.10.2。
进到下载下来的安装包所在目录下打开终端,先获取权限
sudo su
接下来解压缩至指定位置
tar -xavf linux-5.10.2.tar.xz -C /usr/src
添加自定义系统调用
- 进到内核源码解压后的位置,之后的操作未说明的都在这个位置下
cd /usr/src/linux-5.10.2
- 打开自定义系统调用号的syscall_64.tbl文件,在里面添加自定义的系统调用
sudo gedit arch/x86/entry/syscalls/syscall_64.tbl
会有提示让在最后一个common之后添加,这里441是我添加的
添加函数声明和定义
- 打开syscalls.h文件
sudo gedit include/linux/syscalls.h
在末尾添加函数声明
/* My Own syscall */
asmlinkage long sys_mysyscall(int number);
#endif
- 打开 sys.c 文件
sudo gedit kernel/sys.c
在末尾添加函数定义
/* My Own syscall */
SYSCALL_DEFINE1(mysyscall,int,number)
{
printk("mysyscall\n");
printk("The Number You Enter Is %d\n",number);
return number;
}
#endif /* CONFIG_COMPAT */
编译内核
- 净化内核
sudo make mrproper
这条命令会删除所有的编译生成文件、内核配置文件和各种备份文件
sudo make clean
这条命令会删除前一次编译过程中残留的数据
- 配置文件,不需要改什么的话直接Exit
sudo make menuconfig
- 编译内核,j后面的数字是分配的核心数,根据自己得情况来给定
sudo make -j15
为了编译得更快,我直接给了15核,编译5.10.2内核用时16分钟
- 重置内核
sudo make modules_install
sudo make install
到这一步,内核的编译和安装就完成了
- 重启
uname -r
查看当前的内核版本,显示的是我刚刚编译的5.10.2,成功
验证添加的系统调用
- 简单写一段C程序,值“1224”
sudo gedit test.c
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
//441:long sys_mysyscall(int)
long temp;
temp = syscall(441,1224);
printf("mysyscall return %ld\n",temp);
return 0;
}
- 保存、退出,运行这段程序
sudo gcc -o test test.c
sudo ./test
- 查看系统进程
sudo dmesg
可以看到系统调用输出 1224,这个实验就算做完了
总结
- 更换对应版本的国内源
- 安装编译内核需要的依赖
- 下载内核源码
- 添加自定义系统调用
- 编译重置内核
- 验证系统调用是否添加成功