新增 Linux 系统调用
问题描述
新增一个 Linux 系统调用,实现功能:计算一个数字三次方,并打印出来。
具体实现时有三个内容:
- 需要重新编译 Linux 内核;
- 增加一个 Linux 的系统调用;
- 另外写一个程序进行调用。
环境
Windows 10 上 VMware Workstation 14 Pro,Ubuntu(64-bit) 18.04
原内核版本:4.15.0
编译内核版本:4.9.109
(注:若内核版本差距较大,在本文中涉及到的文件可能与实际不同)
详细步骤
前期准备
在 VMware Workstation 上安装 Ubuntu 操作系统。具体步骤可以看这里。
要注意的是,在安装虚拟机前,给系统预留的磁盘空间应该为 40 GB 或更大,否则在解压缩内核文件或编译过程中都会报错。假如你的计算机是多核的,那可以相应地给虚拟机设置多个处理器,这会大大节约后面的内核编译时间。
装好系统后,开机,利用快捷键 Ctrl+Alt+T 打开终端。输入命令 uname -a
,查看该虚拟机系统的初始内核版本,这里是 4.15.0。
在 www.kernel.org 上下载另外一个不同版本的内核,这里的版本号为 4.9.109。最好选择与初始版本接近的内核来编译。
用 su
命令进入 root,依次输入以下命令:
1 | mv linux-4.9.109.tar.xz '/usr/src' |
来移动并且解压缩我们下载的内核文件。
于是我们得到了 Linux 的内核文件,接下来的操作都在此文件夹(*/usr/src/linux-4.9.109*)中进行。
添加系统调用
接下来是修改内核文件。用 gedit 文本编辑器修改 kernel/sys.c 文件,先是加入 linkage.h 头文件:

然后加入系统调用函数,注意要绕过条件编译,也就是 #
间的内容:

修改好了,保存关闭文件。
用 gedit 文本编辑器修改 arch/x86/include/asm/syscalls.h 文件,添加系统调用函数的声明,保存并关闭。如下图:

用 gedit 文本编辑器打开 arch/x86/entry/syscalls/syscall_64.tbl 文件,由于安装了64位系统,所以修改此文件。发现文件中的系统调用编号到 331为止,于是添上 332 号,注意不可以抢占其他已经存在的调用号,按照文件开头注释中标注的 “

配置和编译内核
首先配置编译环境,在 root 状态下输入以下四条命令,安装编译所必要的软件包。
1 | apt-get install libncurses5-dev libssl-dev |
如果在安装过程中出现错误,可以输入 apt-get update
命令更新,再继续安装。
如果是第一次编译,那就使用 make menuconfig
进入配置菜单(如下图),否则输入 make mrproper
清除之前的编译配置。
直接选择默认配置选项,使用键盘上的方向键选择 Exit 退出保存即可。
接下来开始编译内核,命令为 make
,如果在第一步时给虚拟机设置了多个内核,则可以在后面加上 -j*
(*
表示内核个数),可以加快编译速度。如果不知道系统的内核数量,使用命令 lscpu
查看,可以看见我这里的系统是双核。
在编译过程中,要随时注意报错提示,及时解决。不过假如之前的步骤没有做错,大概率是没有错误的。如果有,请善用搜索引擎。
编译时间视机器性能而定。漫长的编译结束后,使用 make modules_install
和 make install
两个命令安装内核模块和内核。
测试结果
重启系统,在开机时的虚拟机模式下,不停地按 Shift 进入 BIOS 界面:
选择第二个高级选项,这里可以看见我们的新内核了!选择进入新编译好的内核版本 4.9.109:
在终端里再次查看内核,已经是更新后的版本了:
编写一个测试程序,其中的 332 就是系统调用号,后面的 3
是传入的参数:
1 |
|
使用 gcc-o my test.c
命令编译程序,使用 ./my
命令运行,结果如下:
计算结果正确!你还可以继续修改传入的参数反复验证结果。
到这里,我们就成功地添加了一个 Linux 的系统调用。