实验准备
实验环境
VMvare Workstation 16 Pro
Ubuntu 20.04.2.0 (内核版本Linux-5.8.0-43-generic)
修改安装的内核版本:Linux-5.4.106 (同样的步骤,5.8.2和4.16.8的都不行.....)
下载地址:西电镜像:https://linux.xidian.edu.cn/mirrors/linux-kernel/ 下linux-5.4.106.tar.xz
虚拟机建议分配70G存储,8核处理器(编译内核会快点)
安装好后在Software&Updates里修改成清华的镜像地址,下载会快点
常用操作
Linux操作
cd +目录 //打开某一目录
ls //列出该目录下所有文件
sudo su //获得管理员权限,建议一打开terminal就用,注意Linux输密码是不显示的,输完直接回车就行
sudo apt-get install+文件名 //下载所需的文件,报错说缺啥就下啥
在终端按上下键可以快速调用历史指令
vim操作
直接按i进入编辑模式
进入后按esc退出编辑模式
输入:可以输入指令进行保存等
:wq 保存并退出
:q! 不保存退出
shift+G快速跳转到最后一行
/加要搜索的内容 查找
需要下载的文件
可能不全,可以根据报错再下载
apt-get install vim 安装vim编辑器
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
sudo apt-get install linux-source kernel-package
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install zlibc minizip
sudo apt-get install libidn11-dev libidn11
sudo apt-get install flex
sudo apt-get install bison

添加系统调用
解压内核
把下载好的压缩包放到虚拟机里,应该任意路径都行
输入 tar -Jxvf linux-5.4.106.tar.xz
添加系统调用函数
解压成功后进入linux-5.4.106/kernel
打开 sys.c文件
vim sys.c
在末尾添加自己编写的函数
asmlinkage long __x64_sys_mycall(void){ //函数名似乎必须命名成__x64_sys_XXXX的形式,不然会报错
printk("啥内容都行");
return 1234; //改成自己喜欢的数字就行
} 
保存并退出
添加声明
进入linux-5.4.106/arch/x86/include/asm/
打开 syscalls.h
vim syscalls.h
插入 asmlinkage long __x64_sys_mycall(void); (别忘记分号)

保存并退出
添加系统调用ID
进入linux-5.4.106/arch/x86/entry/syscalls
打开syscall_64.tbl
vim syscall_64.tbl
添加 335 64 mycall __x64_sys_mycall

保存并退出
编译并安装内核
进入路径linux-5.4.106
清除无用文件
sudo make mrproper
sudo make clean
配置menuconfig
sudo make menuconfig
这里注意一定要把虚拟机窗口最大化,否则可能报错
进入菜单后,先save然后exit然后再exit就行

编译内核
输入 sudo make -j16(jN是让处理器可以同时运行多个编译程序,理论上不能超过处理器核心数两倍,我是8核,所以可以输16)
跑完之后输入sudo make modules,又会跑很久
然后输入sudo make modules_install,开始安装模块
然后输入sudo make install,如果报错让先跑make,那就再跑一次sudo make -j16,再输入sudo make install

显示done就是完成了
如果碰到“debian/canonical-certs.pem”这个错误

在linux-5.4.106路径下输入vim .config
然后查找debian,搜索方法是输入 /,然后输入关键字就可以定位过去
把印号内的内容删掉即可(保留印号)

配置grub引导
输入命令 sudo update-grub2
这样开机的时候就可以引导切换新内核了
切换内核并测试
重启Ubuntu,在小圆圈加载的时候,长按shift,进入引导界面
选择Ubuntu高级选项advanced,然后选择linux-5.4.106进入

进入之后编写测试函数
#include<stdio.h>
#include<sys/syscall.h>
#include<linux/kernel.h>
#include<unistd.h>
int main()
{
long int a = syscall(335); //这里是系统调用号
printf("return %ld\n",a);
return 0;
}跑出来是你编写的系统调用函数return值,而不是-1就大功告成了

参考链接
https://blog.csdn.net/qq_42619368/article/details/89880425
https://blog.csdn.net/Chenciyuan_nj/article/details/115099040