本次实验主要工作是添加一个系统调用并使用,在此过程中需要编译内核。
long my_oper(int* result, int num1, int num2, char* op)
/* 调用my_oper实现四则运算*/
long my_func(int count)
实验用到的内核版本为4.4: linux-4.4.4.tar.xz
xz文件是对tar文件的再次压缩,先用xz命令解压后再用tar命令解压
xz -d linux-4.4.4.tar.xz
tar -xvf linux-4.4.4.tar
进入文件根目录,先make一遍,这里并不会对内核进行全部编译,只是预先生成一些内核必要的文件。
后续操作的根目录为./linux-4.4.4/
arch/x86/include/generated/uapi/asm/unistd_64.h
#define __NR_my_oper 333
其中_NR为内核系统调用前缀,my_oper为系统调用名,333位系统调用对应的编号。注意系统调用号必须唯一。
修改
arch/x86/entry/syscalls/syscall_64.tbl
添加新定义的系统调用声明
333 64 my_oper sys_my_func
注意:此处的系统调用号必须与之前声明的保持一致,my_oper为调用函数名,sys_my_func为实际调用的函数,也就是此处的my_oper必须是unistd_64.h中define __NR_后面定义的系统调用名。
在内核目录下修改
include/linux/syscalls.h
添加声明:
asmlinkage long sys_my_func(int count);`
添加系统调用的实现:在内核目录下
kernel/sys.c
添加具体的实现函数
long my_oper(int* result, int num1, int num2, char* op)
SYSCALL_DEFINE1(my_func, int, count)
至此内核已经系统调用已经添加完毕,现在需要编译内核使得添加的系统调用生效。
在切换到root用户后可以直接编写shell脚本进行内核编译。确认在编译前已经安装libncurses和libssl-dev这两个依赖库,不然在编译中会报curse.h error:No such file or directory。
$ vim KernelCompiler.sh
/* KernelCompiler.sh内容如下*/
#清除编译记录和临时文件
make mrproper
#选择要编译的模块,进入界面之后直接选择save然后exit
make menuconfig
apt-get install libncurses*
apt-get install libssl-dev
#烧写内核镜像(burn image), -j4指定多线程编译参数,最好与处理器核数对应
make bzImage -j4
#编译模块
make -j4 modules
#模块安装
make -j4 modules_install
#安装新内核
make install
/*KernelCompiler.sh */
#添加运行权限
$ chmod +x KernelCompiler.sh
#编译运行
$ ./KernelCompiler.sh
整个过程大概在一个小时左右, make bzImage步骤大概用去15分钟,make modules 和 modules_install大概会耗费50分钟。
编译完成之后利用 uname -a 来查看新内核是否安装成功
为了测试添加的新的系统调用是否生效,我编写了一个测试函数来进行验证
/*
* testSyscall.cc
*/
#include
#include
#include
int main()
{
int count = 10000 * 10000;
/* 通过系统调用333调用自己编写的系统调用,count为参数*/
long ret = syscall(333, count);
printf("result is %ld\n", ret);
return 0;
}