Linux系统调用的实现
前言
一个学期没学操作系统,等到真正想起来要补欠下的实验的时候才发现是真的折磨——前前后后错了有六七遍,于是突然有想法要记录下来整个实验的流程,也让这次实验至少不要完全没有收获。
01 实验内容
- 完成内核编译
- 完成一个系统调用
02 实验环境
- VMware Workstation Pro 16
- Ubuntu 20.04 LTS
- Linux Kernel 5.10.2
VMware安装Ubuntu可参考:教程链接
所有东西尽量从官网进行下载,我好几次实验的失败是由于我在别的渠道下载下来的镜像的问题,真的很折磨。
以及尽量在一开始存储空间选择时就选择分配55GB的内存
1)避免后期编译时空间不足导致编译失败
2)如果不在一开始就分配足够的内存,安装完毕之后想要重新分配非常麻烦(别问我怎么知道的,最后我选择了卸载重装:)
安装完毕后记得更改设置
03 更换国内源
默认的源是外源,国内访问非常慢甚至根本访问不通,所以在实验进行之前我们先将其更换为国内源。
备份原来的源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
打开源文件
sudo gedit /etc/apt/sources.list
修改为对应版本镜像源
一般国内镜像源我们会选择阿里源或者清华源(笔者实验的时候采用的是阿里源,速度会更快一点
阿里源20.04 LTS
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
清华源20.04LTS
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
更新
sudo apt-get update
sudo apt-get upgrade
04 安装编译所需依赖
这一步我在安装时没有出现过问题,看了网上一些资料,如果在这一步报错,有可能是前面镜像源的版本与系统版本不匹配。
sudo apt-get install libc6-dev
sudo apt-get install libelf-dev
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install libidn11-dev libidn11
sudo apt-get install zlibc minizip
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install pkg-config
05 获取内核源码
查看当前所用内核
uname -r (查看当前内核版本
dpkg --get-selections | grep linux(查看所有相关配置文件
一般选择比当前默认版本高的内核,内核源码在官网处下载,我选择的版本是:Linux Kernel 5.10.2(据说这个版本的问题少一些
将安装包保存在某个目录下,然后在这个目录里右键打开终端,输入命令获取权限(如果已经获取权限,后面是在root下输入,不需要加sudo
sudo su
解压缩
tar -xavf linux-5.10.2.tar.xz
06 添加自定义系统调用
首先进入解压缩后内核源码所在目录下
cd linux-5.10.2
打开自定义系统调用号的syscall_64.tbl文件,在最后一个common之后添加自定义的系统调用
sudo gedit arch/x86/entry/syscalls/syscall_64.tbl
07 添加函数声明和定义
打开syscalls.h文件
sudo gedit include/linux/syscalls.h
在末尾添加函数声明
/*mq's syscall */
asmlinkage long sys_mysyscall(int number);
打开 sys.c 文件
sudo gedit kernel/sys.c
在末尾添加函数定义
/*mq's syscall */
SYSCALL_DEFINE1(mysyscall,int,number)
{
printk("mysyscall\n");
printk("The Number You Enter Is %d\n",number);
return number;
}
08 编译内核
净化内核文件
sudo make mrproper
删除各种编译文件、配置文件和各种备份文件
sudo make clean
根据内核已加载的模块自动选择编译范围(比make meunconfig节省时间),一路回车就ok
make localmodconfig
修改配置文件(大坑!!
首先进入配置文件,接着按Ctrl+F搜索CONFIG_SYSTEM_TRUSTED_KEYS,设置为空
如果全部流程选择都和笔者一致,那么.config文件的这个参数本来就是设置为空的
sudo gedit .config
编译(后面的数字有几核用几核
sudo make -j8
编译的最后一个文件夹是sound,可以以此判断编译过程是否中途终止
重置内核(我在这一步倒了很多次,如果这一步没能够成功,检查前面的流程哪里做错了!
sudo make modules_install
sudo make install
09 验证
重启
reboot
查看当前内核版本,如果为刚刚编译的内核版本,则实验成功
uname -r
验证添加的系统调用
- 打开编辑器,写一段c程序
sudo gedit test.c
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
//441:long sys_mysyscall(int)
long temp;
temp = syscall(441,1314);
printf("mysyscall return %ld\n",temp);
return 0;
}
- 保存、退出并运行
sudo gcc -o test test.c
sudo ./test
- 输出1314即为成功
10 PS—内核删除
有几次实验我中途想要更改内核版本,所以直接卸载虚拟机进行重装,后来发现可以直接删内核啊…我是笨比来的
查看所有内核文件
dpkg --get-selections | grep linux
卸载(安装了的文件后面有install字样,卸载后则为deinstall
sudo apt-get remove + 文件名
删除配置文件(更彻底的清除
sudo apt-get purge
更新
sudo update-grub
后话
反正最后实验终于成功了= =,后面几次实验的步骤明明一模一样但还是依旧存在问题(好奇怪哦!!),然后换了个镜像版本就好了(更奇怪了orz),所以计算机真的是玄学吧(确信)。