基于Linux(Ubuntu)系统添加系统调用(虚拟机)
一、简介
Linux内核系统调用(systemcall)所有的操作系统在其内核里都有一些内建的函数,这些函数可以用来完成一些系统级别的功能。Linux系统使用的这样的函数叫做“系统调用”,英文是systemcall。这些函数代表了从用户空间到内核空间的一种转换,例如在用户空间调用open函数,则会在内核空间调用sys_open。一个已经安装的系统的支持的所有的系统调用可以在/usr/include/bits/syscall.h文件里面看到。
二、准备工作
1、装有Ubuntu64位系统的虚拟机
因为编译内核占用较多CPU和大量内存,所以我将虚拟系统的硬盘空间设置为60GB,内存设置为3GB,处理器数量设置为4每个处理器内核数量设置为2,内核总数不能超过电脑原有的内核数。
2、安装VMware Tools
在左上角虚拟机选项里选择安装VMware Tools。将压缩文件提取,进入解压目录,以管理员权限运行vmware-install.pl程序进行安装:sudo ./vmware-install.pl。安装成功后可以在左上角查看选项中选择立即适应客户机。得到如图显示即为安装成功。
3、下载Linux系统内核
内核下载:https://www.kernel.org/ 点击黄色的下载按钮即可,网速较慢请耐心等待。
下载好内核后可直接用鼠标拖入客户机中。(前提是安装了VMware Tools)。
三、注意事项
1、一定要在root状态下输入指令,即在终端输入sudo su进入root状态。
2、建议选择网速较快的网,如下载安装库时中断需要重新下载。
3、建议在编译内核时将主系统和客户机均设置为从不锁屏。
4、虚拟机的内存一定要在至少40G以上,不然会出现内存不够报错。
四、具体实现过程
1、桌面右击打开终端输入sudo su进入root状态,直接输入密码enter即可(密码不会显示在屏幕上,会显示空白)。
2、准备安装软件包
先可把软件与更新设置中的其他软件都勾上,以免出现错误。
①在终端输入:
sudo apt-get install build-essential kernel-package libncurses5-dev
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install zlibc minizip
sudo apt-get install libidn11-dev libidn11
sudo apt-get install bison flex
3、将linux-5.0.10tar.xz移动到/usr/src/文件夹中去
①在终端输入:
sudo mv /home/xu/桌面/linux-5.0.10.tar.xz /usr/src/
xu为我的用户名,根据linux内核版本不同输入的版本号也不同。
4、解压内核文件
①在终端输入:
cd /usr/src
sudo tar -xvf /usr/src/linux-5.0.10.tar.xz
5、进入解压文件
①在终端输入:
cd /usr/src/linux-5.0.10/kernel
6、安装vim编辑器
①在终端输入:
sudo apt-get install vim
7、编辑sys.c文件
(1)用vim打开某个文件之后,键盘输入G 表示到最后一行,之后按 i 进入编辑模式。
(2)编辑好后,按esc键退出编辑模式,然后输入 “:” , 再输入“wq”表示保存并退出。
(3)注意一定要在root状态下编辑,不然无法更改。
①在终端输入:
vim sys.c
②在文档的最末尾加入(看图注意加入的具体位置):
asmlinkage long sys_xutest(void)
{
printk("I am xu.I am adding a system call.2019/4/30");
return 1;
}
8、编辑syscalls.h文件
①在终端输入:
cd /usr/src/linux-5.0.10/arch/x86/include/asm/
vim syscalls.h
②在文档的最末尾加入(看图注意加入的具体位置):
asmlinkage long sys_xutest(void);
9、编辑syscall_64.tbl文件
①在终端输入:
cd /usr/src/linux-5.0.10/arch/x86/entry/syscalls
vim syscall_64.tbl
②在文档的中后位置加入(看图注意加入的具体位置):
335 64 xutest sys_xutest
(335表示自己添加的系统指令的序号)
10、准备编译内核
①在终端输入
cd /usr/src/linux-5.0.10/
make mrproper
make clean
make menuconfig
将General setup改为自己内核的名字,我的改为了xutest。
11、编译内核
①在终端输入:
make -j4
这一步最为核心,耗时最长(约2小时),数字 4 指的是cpu的数量,我虚拟机中配置的cpu数量为4个。
12、安装内核
①在终端输入:
make modules_install
make install
之后重启就行,重启后选择*ubuntu。
13、调用系统指令
重启后在桌面打开终端,进入root状态。
①在终端输入:
uname -r
查看使用的内核,结果显示使用的正是自己刚刚编译好的内核,表示Ubuntu系统的内核编译成功,并且内核成功更换为刚编译的内核。
②在终端输入:
vim test.cpp
③写入如下代码:
#include<iostream>
#include<linux/kernel.h>
#include<syscall.h>
#include<unistd.h>
using namespace std;
int main()
{
cout<<"System call sys_xutest has been used."<<endl;
long a=syscall(335);
cout<<"System call sys_xutest return : "<<(int)a<<endl;
syscall(335);
return 0;
}
保存后退出。
④在终端输入:
g++ test.cpp
会在如下文件夹中生成a.out文件
⑤在终端输入:
./a.out
执行刚刚生成的a.out文件。可以看到返回值为1,正是新增的系统指令的返回值,说明已经成功。但是没有输出语句。原因是系统指令中用的是printk(); 而printk()是由于优先级的问题并不一定能够写到终端上来的。想看到那条输出语句的话,得在日志文件中查看。
⑥在终端输入:
dmesg
五、问题解决
问题1:执行 make mrproper 时显示找不到make命令
apt-get install make
问题2:执行 make menuconfig 时报错
对上面需要安装的库进行重装,如果重装后仍然出现错误类型为recipe for target ‘menuconfig’ failed建议重新下载内核重来。
问题3:编译内核过程中出现无法找到的声明
原因是因为修改syscall_64.tbl文件时写的是模仿上面的写的__x64_sys_xutest,然后改为sys_xutest再编译一遍就没问题了。
问题4:编译内核后客户机无法重启
多次在VMware中重启客户机进行尝试。
六、感想
这次作业算是操作系统的第一次作业,接触到了系统的深层次内容,整个过程也是十分新奇有趣。这次作业的完成的参考部分主要是参考网上的博客,还请教了班内已经完成的同学。
这次作业完成大概经历了三天,其中网络问题给我造成了很大麻烦,首先内核的下载比较慢,再就是在软件包时出现了断网,其实有些软件包没有安装成功,导致后面的步骤报错。
再一个就是没有进入root用户状态,造成了一些文件的写入失败,出现错误。其中最耗时的是编译内核部分,我再第一次编译内核的时候由于没有分配足够的内存空间,导致编译中断而且虚拟机无法重启,我只好重新安装客户机。第二遍做的时候还是比较顺利,在内核编译重启时出现了卡顿,也通过重启解决了问题。总体来说还是比较顺利的。
虽然出现了很多问题,但是解决这些问题之后成就感还是蛮高的,也逐渐对Linux系统产生兴趣,我去年用的是苹果电脑,当时一直无法接受那个系统的使用方法。现在我很享受解决问题这个过程,也积极帮同学解决相似的问题。我非常有兴趣对Linux内核进行深入的了解。最后非常感谢分享自己经验的博客博主们,他们给了我很大帮助。