要么改变世界,要么适应世界

通过编译内核的方式增加系统调用

2020-05-02 09:41:00
113
目录

Ubuntu 版本:20.04 LTS

虚拟机配置:硬盘:40 GB 内存:4 GB

内核版本:5.4.0.26-generic

VMware 版本:15.5.0

前期准备

编译的时候需要一些库,所以要提前安装:

sudo apt-get install libncurses5-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libssl-dev
sudo apt-get install 
sudo apt-get install build-essential
sudo apt-install kernel-package

这么多??好吧,其实不一定需要全部,部分Linux发行版可能自带,可以先跳过这一步,先做后面的事情,前提是自己先做好中途出现error的准备!中途出现错误的话可以根据提示安装即可。

查看自己内核版本

uname -a

我的是 5.4.0.26-generic

下载内核

尽量下载和自己内核相近的内核,避免版本跨度过大引起不兼容情况。下面是网址

http://cdn.kernel.org/pub/linux/kernel

我下载的是linux-5.3.9.tar.xz

解压缩内核文件

首先将上面的内核文件移动到/usr/src/目录下

/usr/src/目录下打开终端

解压

sudo xz -d linux-5.3.9.tar.xz

解包

sudo tar -xvf linux-5.3.9.tar

加入函数

解包完毕之后会出现一个linux-5.3.9文件夹,进入该文件夹的kernel文件夹中

cd linux-5.3.9/kernel


编辑sys.c文件,在末尾加入函数:

asmlinkage long sys_hello(void){
    prink("hello syscall!");
    return 1;
}

添加函数声明

进入/usr/src/linux-5.3.9/arch/x86/include/asm

编辑 syscalls.h,加入我们的sys_hello函数:

给我们的系统调用分配一个id

打开/usr/src/linux-5.3.9/arch/x86/entry/syscalls/syscall_64.tbl

一定要确保不会跟已有的冲突

我加的是

548 64 hello sys_hello

配置内核

进入到/usr/src/linux-5.3.9目录下,依次执行

sudo make mrproper

sudo make clean

sudo make menuconfig

假如执行sudo make menuconfig时候出现下面的错误

将虚拟机全屏即可(撑满屏幕)

然后出现该页面,直接save,然后exit

然后就可以通过下面的命令编译我们的内核了

sudo make

该过程大概持续几个小时,反正我是放后台,然后先去睡觉的~~。

但是!等我睡醒才发现,电脑自动休眠了!白白浪费了一个晚上的时间,所以提醒编译之前将电脑的休眠模式关闭。还有编译过程会产生大量中间文件,建议硬盘给够 40 GB

出现类似上面的信息就说明编译成功了。

生成modules

sudo make modules

这个过程也需要一定的时间。

安装modules

sudo make modules_install

将内核安装进系统中

sudo make install

重启并测试

重启过程进入高级选项

刚刚重启的时候按下ESC(网上说是ESC,但是我的是长按Shift

选择高级选项,然后选择新内核

假如进入内核的过程出现kernel panic not syncing:System is deadlocked on memory错误,只需要将内存增大即可。

新建测试源程序testMyCall.c

#include<stdio.h>
#include<sys/syscall.h>
#include<unistd.h>
#include<stdio.h>
int main(){
    // syscall 需要传递一个系统调用编号
	long int myRetutn = syscall(548);
    printf("syscall return: %ld",myRetutn);
	return 0;
}

编译运行

gcc testMyCall.c -o test
./test
syscall return: 1

我们发现并没有输出hello syscall!,是因为日志输出级别问题,只需要调用dmesg命令即可。

历史评论
开始评论