内核编译新增系统调用,功能:显示当前系统名称和版本
本文为详细操作步骤文,请按照本文所需环境操作,在本文中你能学到内核编译的步骤,了解常见的问题,也了解如何添加系统调用并且使用。
以下所有操作均是在VMware17虚拟机进行,如不懂安装虚拟机请自行搜索教程。
虚拟机配置:
这里着重提醒,虚拟机硬盘必须高于30G,建议跟我设置为50G
以下所有操作和代码,请自己注意大小写和中英文空格、缩进等等问题。
Ubuntu系统下载
https://mirror.tuna.tsinghua.edu.cn/ubuntu-releases/20.04/ubuntu-20.04.6-desktop-amd64.iso
kernel内核下载
https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.15.60.tar.gz
#安装依赖
apt-get install git fakeroot build-essential libncurses5-dev xz-utils libssl-dev bc flex libelf-dev bison dwarves libelf-dev zlibc minizip libidn11-dev libidn11 flex libc6-dev pkg-config openssl gcc vim make g++ kernel-package bin86 zstd rsync tar gnupg2 gzip dwarves bc binutils perl-base libncurses-dev qttools5-dev -y
进入下载的kernel内核包所在目录打开终端
获取当前目录的root权限
sudo su
在当前目录解压kernel内核包
tar -zxvf linux-5.15.60.tar.gz
在当前目录移动kernel内核包到 /usr/src目录
mv linux-5.15.60.tar.gz /usr/src
进入/usr/src/linux-5.15.60目录
cd /usr/src/linux-5.15.60
#添加mysyscall的系统调用号
nano arch/x86/entry/syscalls/syscall_64.tbl
335 common mysyscall sys_mysyscall
#添加mysyscall系统调用的声明,在最后#endif前面添加
nano include/linux/syscalls.h
asmlinkage long sys_mysyscall(void __user *sysname, void __user *release, void __user *version);
#添加系统调用,在最后#endif前面添加,作用:显示系统版本号和系统名称
nano Kernel/sys.c
SYSCALL_DEFINE3(mysyscall,void __user*,sysname,void __user*,release,void __user*,version)
{
struct old_utsname tmp;
down_read(&uts_sem);
memcpy(&tmp, utsname(), sizeof(tmp));
up_read(&uts_sem);
copy_to_user(sysname,&tmp.sysname,sizeof(tmp.sysname));/*将sysname值拷贝到用户空间*/
copy_to_user(release,&tmp.release,sizeof(tmp.release));/*将release值拷贝到用户空间*/
copy_to_user(version,&tmp.version,sizeof(tmp.version));/*将version值拷贝到用户空间*/
printk("sysname = %s \n",tmp.sysname);
printk("release = %s \n",tmp.release);
printk("version = %s \n",tmp.version);
return 0;
}
第一次编译无需执行这个命令,除非有编译过。该命令作用是删除所有编译生成的文件、内核配置文件(.config文件)和各种备份文件
make mrproper
拷贝当前系统配置并为新内核生成配置
cp -v /boot/config-$(uname -r) .config
make localmodconfig
#全都默认回车
# 配置内核
make menuconfig
load → (.config)OK→ SAVE→ (.config)OK → EXIT load后默认.config
#修改.config配置
gedit .config
CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_SYSTEM_REVOCATION_KEYS=""
如不修改提示类似“make[1]: *** No rule to make target ‘debian/certs/benh@debian.org.cert.pem’, needed by ”
#可能需要修改
CONFIG_FRAME_WARN=2048
主要是因为内核中设置了堆栈报警大小,其默认为1024bytes
# 构建内核
make -j$(nproc) bzImage
正确编译完成会出现bzImage的路径,这时就可以接着下一步。
make -j$(nproc) modules
sudo make modules_install
sudo cp arch/x86/boot/bzImage /boot/vmlinuz-5.15.0.60-generic
sudo make install
sudo update-grub
重启系统
sudo reboot
新建test.c测试文件
nano test.c
写入代码:
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
/*335 myshow name asmlinkage long sys_mysyscall(void __user *sysname,void __user *release,void __user *version);*/
int main()
{
char sysname[100],release[100],version[100];
syscall(335,sysname,release,version);
printf("Sysname:%s\nRelease:%s\nVersion:%s\n",sysname,release,version);
}
保存ctrl+o 退出 ctrl+x
编译test.c
gcc test.c -o test
运行
./test
追踪系统调用
strace ./test