一、写作目的
这次给大家分享下怎么在Ubuntu上自己添加系统调用。之前已经写过怎么在Ubuntu 18.04上自己编译并且安装内核(https://blog.csdn.net/qq_36290650/article/details/83052315),这次承接上次的操作,在Ubuntu 18.04+内核4.18.14上添加系统调用。
二、操作步骤
1.在文本结尾增加自己的系统调用函数和其对应的系统调用编号
执行以下命令
/usr/src/linux-4.18.14/arch/x86/entry/syscalls #内核源代码所在根目录
sudo gedit syscall_64.tbl #系统调用入口表文件
#这里的 gedit 是Ubuntu中,具有图形界面的编辑器。您也可以替换成例如 vi、vim、nano 等命令行或者其它编辑器
以下为我自定义的系统调用相关信息: < 假设要添加的函数为 long sys_HelloWorld(void)、long sys_AddValueWithOne(int arg) >
系统调用编号:336 <number:可以理解为系统调用的标识符>
适用位数:common <abi:x86/64/common>
名称:HelloWorld <name:自定义名称>
函数名:sys_HelloWorld <entry point:自己添加的系统调用的函数名>
系统调用编号:337 <number:可以理解为系统调用的标识符>
适用位数:common <abi:x86/64/common>
名称:AddValueWithOne <name:自定义名称>
函数名:sys_AddValueWithOne <entry point:自己添加的系统调用的函数名>
注:如果是仅支持32位系统的系统调用,系统调用编号不得小于512
故添加的系统调用如下图所示:
保存并退出
2. 添加系统调用函数的声明
执行以下命令
cd /usr/src/linux-4.18.14
sudo gedit include/linux/syscalls.h
在打开的文章末尾(endif 前面)加入自定义函数的声明
保存并退出
3. 添加系统调用函数定义
执行以下命令
cd /usr/src/linux-4.18.14
sudo gedit kernel/sys.c
在打开的文章末尾(endif 前面)加入自定义函数的定义部分,注意,打印用内核函数"printk"
保存并退出
4.编译内核
输入以下指令
sudo make clean #清理之前的编译残留
sudo make oldconfig #一直按回车就好
sudo make -j4 #4是指多线程编译的个数
sudo make modules_install #安装要使用原来旧内核版本,在欲安装的内核目录下安装
sudo make install #同上一个安装
sudo reboot #重启进入新内核就好
uname -a #查看内核版本
三、验收成果
1.编写如下C代码
首先进入路径,创建测试代码
#首先执行下面两行命令
sudo cd ~/Desktop/
sudo gedit test.c
test.c中内容如下,保存后退出
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char **argv)
{
//336:long sys_helloworld()
printf("System call sys_helloworld return %ld\n",syscall(336));
//336:long sys_AddValueWithOne(int)
printf("System call sys_AddValueWithOne return %ld\n",syscall(337,2));
return 0;
}
2.编译并运行代码
sudo gcc -o test test.c
sudo ./test
你将会看到下图所示结果
注:第二个函数参数尚未正常传递,所以看到是“随机数”,感谢热心的朋友在评论区提醒,后续经过验证,是因为Ubuntu的内核版本曾经在某一版本以后有所变化导致此方法失效,经验证 14.04版本可行
最后,如果你经过上面的步骤依旧不能成功(比如总是返回-1),建议查看下系统内核版本(uname -a),也许你在32位系统上添加了64位调用