Linux添加系统调用

简介

设计并实现一个新的内核函数 mycall( ),此函数通过一个引用参数的调用返回当前系统时间,功能上基本与 gettimeofday( )相同。操作系统的实验作业,给的参考资料还在用2.4.x的内核,自己查了一些资料,做了4.15.3内核的添加系统调用,供大家参考。

前提准备

在win10操作系统下使用VMware安装Ubuntu16.04.5 64位。如果你使用的Ubuntu版本过于老旧,可能无法成功。关于如何在虚拟上安装Ubuntu,可以参阅我的另一篇文章写给萌新的教程:win10下使用VMware安装Ubuntu16.04.5 Gnome

注:虚拟机硬盘空间应分配一定的大小,至少30G吧。下图为我编译安装内核后的空间占用情况。

 

5656674-2671153bd58ffb62.png

空间使用

下载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

5656674-6c9074146e3d0869.png

ls

修改syscall_64.tbl文件为其在342行添加一行内容,最前面的333位系统调用号,之前的系统调用号用到了332,所以这里是333

333   64    mycall    sys_mycll

5656674-e88ffb4b72dc1b8d.png

修改syscall_64.tbl后

 

3.申明系统调用服务例程原型
在linux-4.15.3/include/linux目录下修改syscalls.h文件
在最后的#endif之前添加以下内容

asmlinkage long sys_mycall(struct timeval *tv);

纠错:图片中943行前少了一个a,被我不小心删掉了。

 

5656674-2066c2cf9d7772f0.png

添加原型

 

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

5656674-c3bfd7787776ae36.png

失败示例

 

成功的话,如下所示,左右移动选择Save回车确认即可

 

5656674-cb3636185b03ead5.png

成功

 

ok确认即可。

 

5656674-fd4d80744b60f6b9.png

2018-12-05_192247.png


之后选择Exit退出即可。

  1. 编译安装
# 编译,这里根据你为虚拟机分配的物理核决定 -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

5656674-899afbcc76615568.png

测试


版权声明:本文为m0_37194132原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。