Linux内核编译-4.4版本及添加系统调用

本次实验主要工作是添加一个系统调用并使用,在此过程中需要编译内核。

1 实验内容

1.向Linux内核增加新的系统调用,实现整数四则运算的系统功能。
2.四则运算函数原型:
long my_oper(int* result, int num1, int num2, char* op)
3.系统函数原型:
/* 调用my_oper实现四则运算*/
long my_func(int count)

2 实验步骤

2.1 内核下载

实验用到的内核版本为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/

2.2 新增系统调用号

  • 在内核目录下修改
arch/x86/include/generated/uapi/asm/unistd_64.h
  • 添加新的系统调用号:
#define __NR_my_oper 333

Linux内核编译-4.4版本及添加系统调用_第1张图片
其中_NR为内核系统调用前缀,my_oper为系统调用名,333位系统调用对应的编号。注意系统调用号必须唯一。

2.3 修改系统调用向量表

修改

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_后面定义的系统调用名。

Linux内核编译-4.4版本及添加系统调用_第2张图片

2.4 添加系统调用函数声明

在内核目录下修改

include/linux/syscalls.h

添加声明:

asmlinkage long sys_my_func(int count);`

Linux内核编译-4.4版本及添加系统调用_第3张图片`

2.5 添加系统调用的实现函数

添加系统调用的实现:在内核目录下

kernel/sys.c

添加具体的实现函数

 long my_oper(int* result, int num1, int num2, char* op)

Linux内核编译-4.4版本及添加系统调用_第4张图片
添加SYSCALL_DEFINE1调用my_oper

SYSCALL_DEFINE1(my_func, int, count)

Linux内核编译-4.4版本及添加系统调用_第5张图片

2.6 编译安装新内核

至此内核已经系统调用已经添加完毕,现在需要编译内核使得添加的系统调用生效。
在切换到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 来查看新内核是否安装成功

2.7 编写用户测试函数

为了测试添加的新的系统调用是否生效,我编写了一个测试函数来进行验证

/*
* 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;
}
  • 实验结果分析
    这里写图片描述

可以看到这里函数的返回值是0,说明新增的系统调用成功运行。
通过$dmesg命令查看内核日志
Linux内核编译-4.4版本及添加系统调用_第6张图片

你可能感兴趣的:(Linux内核,系统编程)