title: 西电软工OS实验专题二–增加系统调用
date: 2022-05-14 07:48:48
tags: OS
写在前面:
如果这个过程中你某个地方没有把握,切记使用vm的快照功能,血的教训,但是要注意自己的磁盘大小,快照也很占磁盘的
本章参考了前辈*@编程菜玑*的文章,在其文章的基础上对于出现的一些error进行了修复:https://blog.csdn.net/qq_45289233/article/details/106621835?ops_request_misc=&request_id=&biz_id=102&utm_term=ubuntu%E5%A2%9E%E5%8A%A0%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-4-106621835.nonecase&spm=1018.2226.3001.4187
题目要求:
为Linux内核增加一个系统调用,并编写用户进程的程序来测试。
要求该系统调用能够完成以下功能:
(1) 该系统调用有1个整型参数或字符串型参数,接收输入自己的学号;
(2) 若参数为奇数,则返回自己学号的最后5位。如你的学号为16130120101 ,则返回20101;
(3) 若参数为偶数,则返回自己的学号的最后6位。如你的学号为16130120102 ,则返回120102 。
提交内容为:
截图1: 运行结果
截图2:源代码
虚机设置:
vmware:16.2.0
这里建议将处理器尽量拉高,硬盘也最好分配到60G及以上为好
这个是我的设置:
Ubuntu:
输入
uname -a
查看自己的版本号和内核号:
Ubuntu:20.04.1(镜像下载链接:
http://lib.lilijiu-blog.top/os%E4%B8%93%E9%A2%98%E4%BA%8C/ubuntu-20.04.3-desktop-amd64.iso)
这个链接。。下载速度极慢,建议自己去官网下
kernel:5.13.0
注意Ubuntu的系统一般不要用最新版,很容易报错
下载一个新内核
可以去官方网站www.kernel.org看看
我们选择这个版本:
下载Linux-5.15.41内核版本,将压缩包复制到虚拟机的桌面
这里注意一下,我之前用的时候是5.15.40版本的,结果写教程的时候更新到了41,后面我懒得再改了,自己替换一下。注意这个也不要用最新版,最新版总是莫名其妙的bug.
打开终端:
cd Desktop//进入桌面
sudo su //输入这个之后就不要关闭终端了,如果关闭了的话要再执行一次这个命令
//或者说之后的每条命令前面都增加一个“sudo”也可以
//sudo 的作用是提供管理员权限,后面如果在运行的过程中出现“permission necessary”的error就是没有使用sud0给予管理权限
//输入密码,回车
mv linux-5.15.40.tar.xz /usr/src //将桌面上的新内核包移动到/usr/src
cd
cd /usr/src
tar -xvf linux-5.15.40.tar.xz //解压缩
随后输入:
ls
看到如下界面就表示成功:
安装依赖包
输入:
cd
apt-get update
apt-get install libncurses5-dev libssl-dev
apt-get install build-essential openssl
apt-get install zlibc minizip
apt-get install libidn11-dev libidn11
apt-get install bison
apt-get install libelf-dev
apt-get install flex
apt-get install pkg-config
apt-get install libc6-dev
apt-get install dwarves
apt-get install libzstd-dev
apt install zstd
添加系统调用
//进入新内核目录
cd /usr/src/linux-5.15.40
//编辑系统调用入口表
cd arch/x86/entry/syscalls
gedit syscall_64.tbl
会出现这么一个界面:
这个就是系统调用表,系统调用入口表分为两段,第一段的系统调用号末尾在300-400以内,第二段从512开始,我们找到第一段的末尾在它后面添加系统调用号和名字
如图所示:
我的系统第一段系统调用号在334结束,所以我增加的系统调用号为335,以后我们使用系统调用时需要使用335,这个号码来调用每个人的号都有可能不同,然后我的系统调用名为mysyscall,可以自己任意取,sys_mysyscall是接下来要添加了函数名称(以sys_开头),添加完后,点击右上方的保存,然后退出。
添加系统调用声明
cd
cd /usr/src/linux-5.15.40
gedit include/linux/syscalls.h
打开后直接到翻到快到末尾的位置找到这样几行代码:
添加代码:
asmlinkage long sys_mysyscall(unsigned long long);//sys_后面的函数名要和上面的对应
如图所示:
保存退出
添加函数定义:
gedit kernel/sys.c
在倒数第二行写函数:
SYSCALL_DEFINE1(mysyscall,unsigned long long,num)
{
int mod;
unsigned long long result,x;
long m;
x=2;
result=num;
mod=do_div(result,x);
if(mod)
{
x=100000;
m=do_div(num,x);
printk("result is %05ld\n",m);
return m;
}
else
{
x=1000000;
m=do_div(num,x);
printk("result is %06ld\n",m);
return m;
}
}
保存退出
编译内核
//以下步骤都需要在/usr/src/linux-5.15.40下执行
make mrproper
make clean
make oldconfig //一直回车就好
//修改config文件
gedit .config
//找到并修改CONFIG_SYSTEM_TRUSTED_KEYS,将其赋空值,如下:
CONFIG_SYSTEM_TRUSTED_KEYS=""
//如果CONFIG_SYSTEM_REVOCATION_KEYS的值不为空的话,也将其赋空值,如下:
CONFIG_SYSTEM_REVOCATION_KEYS=""
make -j12//这里也可以写2或者4或者8,根据你的内核数来,可以低但不能高
make modules_install
make
make install
update-grub
reboot
重启后输入uname -a,看内核是否改变,改变了就算成功
编写测试代码
cd Desktop
gedit test.c
#include<linux/kernel.h>
#include<sys/syscall.h>
#include<unistd.h>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
int main(){
printf("result is %ld\n",syscall(335,20009200384));
return 0;
}
保存,退出
gcc -o test test.c
./test
查看内核函数输出:sudo dmesg