Linux编译内核和添加系统调用

Linux编译内核和添加系统调用

目的

  1. 采用编译内核的方法,添加一个新的系统调用,实现文件拷贝功能

  2. 编写一个应用程序,测试新加的系统调用

环境和步骤

开发环境

  • 操作系统:ubuntu 16.04 LTS 64位
  • 内核版本:linux-4.14.141
  • 内存:8G
  • 处理器:Intel® Core™ i5-6200U CPU @ 2.30GHz × 4
  • 编辑器:Vim
  • 编译器:gcc version 5.4.0

步骤

  1. 下载内核源码并解压,下载版本为linux-4.14.141

  2. 编写添加到内核中的新的系统调用例程,将例程添加到linux-4.14.141/kernel/sys.c文件中

  3. 连接新的系统调用,在linux-4.14.141/include/linux/syscalls.h文件中添加新的系统调用的函数定义,在linux-4.14.141/arch/x86/entry/syscalls/syscall_64.tbl系统调用表中为新增的系统调用分配一个系统调用号和系统调用名

  4. 配置编译内核所需环境

$ sudo apt-get install libncurses* 
$ sudo apt-get install build-essential openssl 
$ sudo apt-get install zlibc minizip 
$ sudo apt-get install libidn11-dev libidn11
  1. 将内核源码拷贝到/usr/src目录下,进入内核源码目录,在该目录打开终端,进入超级用户权限
  2. 生成配置文件.config,在终端执行
$ make menuconfig
  1. 多线程编译内核
$ make -j8
  1. 生成并安装模块
$ make modules_install
  1. 安装新系统
$ make install
  1. 重启,选择新修改的内核

  2. 编写应用程序,测试新增的系统调用

核心代码

添加系统调用例程

  1. 函数定义使用了宏定义SYSCALL_DEFINEx,x代表参数数目,新增例程需传入2个参数,故x为2;宏定义第一个参数为系统调用名mycopy,而后为参数类型申明const char __user *__user标记了参数是从用户空间传入,即传入的文件名,故函数定义为:
SYSCALL_DEFINE2(mycopy, const char __user *, _target, const char __user *, _source)
  1. 系统调用提供了用户程序和操作系统之间的接口,应用程序通过系统调用实现其与 OS 的通信,并可取得它的服务。故系统调用总数默认传入参数来自用户空间,此时在内核中调用内核函数传入参数,则需要将用户空间参数拷贝到内核空间,防止因KPTI(内核页表隔离)产生访问错误,调用函数strndup_user将文件名从用户空间拷贝到内核空间:
target = strndup_user(_target,PAGE_SIZE);
source = strndup_user(_source,PAGE_SIZE);
  1. 调用sys_opensys_readsys_write函数时,为保护内核空间,会首先对参数进行检查,为防止发生段错误,需要通过设置set_fs(KERNEL_DS)将其能访问的空间限制扩大到内核空间,在完成内核函数调用返回用户空间时,需恢复成原来的访问范围:
mm_segment_t fs;
fs = get_fs();     //get access restriction value
set_fs(get_ds());  //set kernel restriction value

返回之前恢复:

// close file
sys_close(tar_fd);
sys_close(sor_fd);
set_fs(fs);  //recovery

syscalls.h文件中添加新增系统调用例程函数声明

asmlinkage long sys_mycopy(const char __user *target, const char __user *source);

syscall_64.tbl系统调用表中添加新增系统调用号

# mycalls 
333 64  hello_world     sys_hello_world
334 64  mycopy          sys_mycopy

测试

  1. 使用uname -r命令查看当前系统内核版本

    查看内核版本

  2. gcc编译测试程序并运行

    测试系统调用

测试代码目录说明

开源地址OS_Kernel/compile_kernel&add_syscall

compile_kernel&add_syscall 编译内核和添加系统调用代码目录

Linux编译内核和添加系统调用.md

test_pro 测试程序文件夹

IOT 测试源文件

IOT1 拷贝结果

test_copy.c 测试源程序代码

test_copy 编译生成的二进制程序

example.c 内核空间访问说明示例程序

syscall_64.tbl 系统调用表

syscalls.h 系统调用头文件

sys.c 系统调用函数定义源文件

test_copy.c 测试自定义拷贝系统调用源程序代码

test_hello.c 测试自定义打印"hello"的系统调用

mycopy.c 需要修改的文件内容总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值