实验目的
本次实验主要是完成一个简单四则运算的系统调用,同时在用户态实现一个相同功能的代码,比较系统调用与普通用户态的时间开销,分析时间差异性。
实验环境
系统版本 Ubuntu 18.0.4
当前linux内核版本 linux4.15.0-101
需要重新编译的linux版本 4.10.1
实验内容
本次实验主要涉及以下三个方面的内容:
第一、添加自定义的系统调用,这一块主要涉及:添加系统调用号、在系统调用分派表中添加对应项、添加系统调用函数声明、系统调用函数实现
第二、编译内核,这是比较痛苦且漫长的过程,中间会有很多问题
第三、编写相应的代码,完成实验。
添加自定义的系统调用
首先获取 4.10.1版本的linux内核,我这里贴一个网址,速度比官网快很多的。不同版本的linux内核下载地址,下载后放到/usr/src/目录下,然后解压,如下图所示。
打开相应文件夹,第一步添加系统调用分配表,打开目录/usr/src/linux-4.10.1/arch/x86/include/generated/uapi/asm,如下图所示
在unistd_64.h中添加自己的系统调用号,本次实验中我使用333作为新的系统调用号
注:如果你是第一次下载该内核,且没有编译过这一步可以直接跳过,因为这个generate文件夹是在编译过程中生成的,最初没有。
第二步,向系统调用分派表中添加相应的项。到文件夹/usr/src/linux-4.10.1/arch/x86/entry/syscalls下,打开syscall_64.tbl文件,添加相应项。
第三步,添加系统调用。到文件夹/usr/src/linux-4.10.1/include/linux下,打开文件syscalls.h,添加函数声明。第一、二步骤涉及硬件方面的操作,主要是系统中断到找到这个函数的地址(80中断软中断),找到这个函数地址之后就要进行软件层面的调用。所以前面的文件修改都在arch下。
第四步,添加函数实现。到文件夹/usr/src/linux-4.10.1/kernel下,打开sys.c文件,添加系统调用实现,
注意函数参数中类型和变量名之间有逗号。
至此我们的第一步就完成了。这个过程还是很简单的,此过程要注意的是一些文件可能因为linux的版本不同而导致放置的位置不同,所以要结合自己的linux版本找到对应的文件。
编译linux内核
这是耗时最长的一步,我花了整整一天才搞定。编译内核首先需要一些工具,这些工具在遇到问题时,会提示你缺少某些文件或者组件之类的,你只需要安装对应的工具即可这个问题比较简单,我假设现在已经有了完备的工具可以进行编译工作了。
第一步,回到linux内核的根目录下/usr/src/linux-4.10.1,make menuconfig 或者 make oldconfig,总之如果你直接make bzImag提示出错,就按提示来操作。
执行make bzImage -jx (x是线程数)
注意这个I不是L而是大写的i。这一步会生成一个压缩的linux内核的压缩镜像,这个由setup.bin和vmlinux.bin链接而成,前者主要是做一些开机的硬件引导工作。这一步会出现以下错误。
上网搜索过后才知道我们需要对/usr/src/linux-4.10.1/include/linux下的log2.h和/usr/src/linux-4.10.1/tools/include/linux/下的log2.h文件打补丁,打补丁的目的大致是要弃用____ilog2.NaN这个函数,补丁内容如下
diff --git a/include/linux/log2.h b/include/linux/log2.h
index ef3d4f67118c..c373295f359f 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -16,12 +16,6 @@
#include <linux/bitops.h>
/*
- * deal with unrepresentable constant logarithms
- */
-extern __attribute__((const, noreturn))
-int ____ilog2_NaN(void);
-
-/*
* non-constant log of base 2 calculators
* - the arch may override these in asm/bitops.h if they can be implemented
* more efficiently than using fls() and fls64()
@@ -85,7 +79,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
#define ilog2(n) \
( \
__builtin_constant_p(n) ? ( \
- (n) < 1 ? ____ilog2_NaN() : \
+ (n) < 2 ? 0 : \
(n) & (1ULL << 63) ? 63 : \
(n) & (1ULL << 62) ? 62 : \
(n) & (