Ubuntu上增加系统调用(需要编译内核)

写这篇的原因以及目的

  • 最近老师布置了一个任务在Ubuntu中添加一个自己的系统调用,很多同学都完成得比较好,可能因为自己太蠢,花了很久很久很久很久才完成,也走了很多弯路,用的是虚拟机,重装过一两次 也用了不下六次恢复快照

恢复快照:用虚拟机VMware时,在某一时候使用快照功能,在这之后如果出现了操作失误、系统出问题或者我们将要进行的编译内核失败,可以直接恢复到出问题之前的状态。具体操作可以自行百度,使用比较简单。

  • 这几天也看了几篇类似的博客跟着做,但多多少少都出了点问题后者是讲得不够清楚,决定自己总结一下。

大致步骤

  1. 下载新内核
  2. 添加系统调用
  3. 编译内核
  4. 测试

具体步骤

  1. 下载linux内核

需要下载一个新的Linux内核,在linux内核官方网站www.kernel.org下载
Ubuntu上增加系统调用(需要编译内核)_第1张图片

我们选择最新的稳定版本,我这里是5.6.15,视最新的版本而定。

下载好后得到一个压缩包,直接拉到Ubuntu里,这里我将压缩包放在了桌面上

Ubuntu上增加系统调用(需要编译内核)_第2张图片

  1. 安装一些用于编译内核的依赖包
//先更新软件源
sudo apt-get update

再安装依赖包

Ubuntu上增加系统调用(需要编译内核)_第3张图片

这里总共是九条命令,一条一条的敲吧,不敲后面可能会出错

  1. 解压缩新内核

将刚刚下载的新内核解压缩到 /usr/src 下

Ubuntu上增加系统调用(需要编译内核)_第4张图片


添加系统调用

  1. 进入新内核开始增加系统调用
//进入新内核目录
cd /usr/src/linux-5.6.15

进入新内核以下执行都操作没有特别声明均在 /usr/src/linux-5.6.15 目录下执行

  • 编辑系统调用入口表
sudo gedit /usr/src/linux-5.6.15/arch/x86/entry/syscalls/syscall_64.tbl 

系统调用入口表分为两段,第一段的系统调用号在300-400以内,第二段从512开始,我们找到第一段的末尾在它后面添加系统调用号和名字

Ubuntu上增加系统调用(需要编译内核)_第5张图片

这里第一段系统调用号在438结束,所以我们增加的系统调用号为439,以后我们使用系统调用时需要使用439这个号码来调用每个人的号都有可能不同,然后我的系统调用名为mysyscall,

可以自己任意取,sys_mysyscall是接下来要添加了函数名称(以sys_开头),添加完后,点击右上方的保存,然后退出。

  • 添加系统调用函数声明
cd /usr/src/linux-5.6.15
sudo gedit include/linux/syscalls.h 

打开后直接到翻到最末尾添加一个函数声明

Ubuntu上增加系统调用(需要编译内核)_第6张图片

注意此时的函数名 sys_mysyscall() 应与上一步在系统调用表中的添加的一致,同上保存然后退出。

  • 添加系统调用的函数定义

也就是使用系统调用时执行的程序

cd /usr/src/linux-5.6.15
sudo gedit kernel/sys.c

Ubuntu上增加系统调用(需要编译内核)_第7张图片

这里我使用内核函数 printk() 打印我的学号和姓名,然后返回0,程序执行成功则会返回0 ,但是 printk() 打印并不是打印在终端命令行中,而是日志文件,后面我们再说如何查看到printk()打印的信息。同样地保存和退出这个文件。

至此,系统调用添加步骤已经完成,下面开始编译内核。


编译内核

编译内核之前,建议使用虚拟机的朋友 拍摄此时虚拟机的快照,方便编译内核失败时直接恢复到现在的状态

开始编译内核

  1. 编译内核

我是在 /usr/src/linux-5.6.15目录下执行,根据自己下载的内核版本而定 /usr/src/linux-xxxx

cd /usr/src/linux-5.6.15
make mrproper //得到源代码,将其净化
  • 将旧内核的配置信息拷贝到当前目录下 并命名为 .config (直接使用了旧内核的其他配置信息)

先查看旧内核的配置文件名,在/boot目录下

ls /boot

Ubuntu上增加系统调用(需要编译内核)_第8张图片

以config 开头的为旧内核配置文件,将这个文件拷贝,我这里文件名为 config-5.3.0-53-generic

cp /boot/config-5.3.0-53-generic ./.config
  • 对内核选项进行配置

此时已经有了 .config 文件,对内核选项进行配置

make menuconfig

Ubuntu上增加系统调用(需要编译内核)_第9张图片

Ubuntu上增加系统调用(需要编译内核)_第10张图片

Ubuntu上增加系统调用(需要编译内核)_第11张图片

Ubuntu上增加系统调用(需要编译内核)_第12张图片

Ubuntu上增加系统调用(需要编译内核)_第13张图片

make clean //删除配置时留下的一些不用的文件,第一次编译可以不用敲
  • 编译内核
make bzImage -j4

上面 -j4 指的是用四个处理器编译,也可以为2,一般为偶数

如果用两个核编译,则:

make bzImage -j2

上面两条命令只用敲一条

这个步骤差不多需要十五分钟

  • 编译模块
make modules -j4

同样也可以 -j2
这个步骤需要一个多小时

  • 安装模块
make INSTALL_MOD_STRIPE=1 modules_install

执行完这条命令后, /lib/modules 目录下应该生成一个 5.6.15 (版本号)目录

mkinitramfs /lib/modules/5.6.15 -o /boot/initrd.img-5.6.15-generic

内核已经全部编译完成,接下来拷贝内核映像

把内核映像和System.map拷贝到 /boot 下

cp /usr/src/linux-5.6.15/arch/x86/boot/bzImage /boot/vmlinuz-5.6.15-generic
cp /usr/src/linux-5.6.15/System.map  /boot/System.map-5.6.15
ln -s /boot/System.map-5.6.15 /boot/System.map

最后一步更新grub配置文件

cd /boot/grub
chmod 777 grub.cfg
update-grub

重新启动Ubuntu机器可以看到自己的新内核

测试

重新启动机器后,用一个C文件测试

执行439号系统调用

sudo gedit test.c
#include 
#include 
#include 
#include 
 
int main(int argc,char **argv)
{
	//439:long sys_mysyscall()
	printf("System call sys_mysyscall return %ld\n",syscall(439));	
	return 0;
}

Ubuntu上增加系统调用(需要编译内核)_第14张图片

编译运行

gcc -o test test.c
./test

运行结果:

在这里插入图片描述

回忆一下系统调用的内核函数:

Ubuntu上增加系统调用(需要编译内核)_第15张图片

返回 0 说明执行成功,但是现在没有看到打印信息,因为打印信息打在了日志文件中

我们dmesg查看日志文件

dmesg

Ubuntu上增加系统调用(需要编译内核)_第16张图片

成功看到了打印信息

至此,添加系统调用就已经成功完成了!!!

希望看到这个博客的朋友能一次成功,不要像我一样…

你可能感兴趣的:(Linux,linux,内核,ubuntu)