简介
设计并实现一个新的内核函数 mycall( ),此函数通过一个引用参数的调用返回当前系统时间,功能上基本与 gettimeofday( )相同。操作系统的实验作业,给的参考资料还在用2.4.x的内核,自己查了一些资料,做了4.15.3内核的添加系统调用,供大家参考。
前提准备
在win10操作系统下使用VMware安装Ubuntu16.04.5 64位。如果你使用的Ubuntu版本过于老旧,可能无法成功。关于如何在虚拟上安装Ubuntu,可以参阅我的另一篇文章写给萌新的教程:win10下使用VMware安装Ubuntu16.04.5 Gnome
注:虚拟机硬盘空间应分配一定的大小,至少30G吧。下图为我编译安装内核后的空间占用情况。
空间使用
下载linux内核4.15.3。可以去tuna镜像站下载,点击此处下载。或者在终端下下载
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.15.3.tar.xz
# ipv6可用时
wget -6 https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-4.15.3.tar.xz
实验步骤
1.解压文件
tar xvJf linux-4.15.3.tar.xz
2.分配系统调用号,修改系统调用表
cd linux-4.15.3/arch/x86/entry/syscalls/
ls
ls
修改syscall_64.tbl文件为其在342行添加一行内容,最前面的333位系统调用号,之前的系统调用号用到了332,所以这里是333
333 64 mycall sys_mycll
修改syscall_64.tbl后
3.申明系统调用服务例程原型
在linux-4.15.3/include/linux目录下修改syscalls.h文件
在最后的#endif之前添加以下内容
asmlinkage long sys_mycall(struct timeval *tv);
纠错:图片中943行前少了一个a,被我不小心删掉了。
添加原型
4.实现系统调用服务
在linux-4.15.3/kernel/sys.c中添加相应的服务
SYSCALL_DEFINE1(mycall, struct timeval *, tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if(copy_to_user(tv, &ktv, sizeof(ktv) ) ) {
return -EFAULT;
}
return 0;
}
5.安装相关依赖
sudo apt install libncurses5-dev libssl-dev build-essential openssl zlibc minizip libidn11-dev libidn11 libelf-dev
6.开始编译
打开终端进入linux-4.15目录下,执行以下命令
# 清楚清除残留的文件,如果编译失败,需要重新编译则需要清除,第一次编译可以不执行
sudo make mrproper
sudo make clean
选择配置,注此条命令要求终端具有一定的宽度,否则会失败
sudo make menuconfig
失败示例
成功的话,如下所示,左右移动选择Save回车确认即可
成功
ok确认即可。
2018-12-05_192247.png
之后选择Exit退出即可。
- 编译安装
# 编译,这里根据你为虚拟机分配的物理核决定 -jn,相同即可
sudo make –j8
或者 sudo make
# 安装内核模块
sudo make modules_install
# 安装内核
sudo make install
8.测试新的系统调用
重启系统,编写测试程序test.c
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <stdio.h>
#define __NR_mycall 333 //系统调用号
int main() {
struct timeval gettime;
struct timeval mycalltime;
gettimeofday(&gettime, NULL);
syscall(__NR_mycall, &mycalltime);
printf("gettimeofday:%ld %ld \n", gettime.tv_sec, gettime.tv_usec);
printf("mycall : %ld %ld \n", mycalltime.tv_sec, mycalltime.tv_usec);
return 0;
}
编译并运行
gcc test.c
./a.out
测试