Linux内核实验 (内核编译)添加系统调用

操作系统实验作业,顺便记录一下过程
就不具体说一些概念了。

实验目标

通过分析Linux内核源代码和新增一个系统调用的方式,达到对操作系统软件结构及其系统调用实现原理的深入理解,并基本掌握操作系统的改造方法

实验环境

VM虚拟机上搭建的 Ubuntu18.04
编译的内核是 linux4.16.10 版本
可以根据需要去官网下载,给出2个内核版本
linux-4.16.10.tar.xz
inux-4.16.8.tar.gz

实验过程

先安装相关的依赖

sudo apt-get install build-essential 
sudo apt-get install kernel-package  
sudo apt-get install libncurses5-dev
sudo apt-get install flex 		// flex bsion 防止后面一些报错
sudo apt-get install bison		

解压内核
把下载好的内核移动到/usr/src/

sudo mv '文件路径'/linux-4.16.10.tar.xz /usr/src/

把下载好的内核解压

cd /usr/src
sudo tar -xvf /usr/src/linux-4.16.10.tar.xz

如果要确定自己的内核版本,可以在终端输入命令

uname -r

图
进入解压好的内核文件目录中

cd /usr/src/linux-4.16.10/kernel

编写我们的系统调用

打开sys.c文件 (三选一 后面就不都写出来了 都写成gedit 看个人喜好)

sudo gedit sys.c    	gedit只能用在图形界面上
sudo vi sys.c
sudo vim sys.c	

添加一个我们定义的函数作为系统调用(简单示范打印一个hello world)

asmlinkage long sys_helloworld(void){
    printk( "helloworld!");
     return 1;
} 

这里我用的 gedit 打开
Linux内核实验 (内核编译)添加系统调用_第1张图片
添加系统调用声明

cd /usr/src/linux-4.16.10/arch/x86/include/asm/
sudo gedit syscalls.h

添加一个声明

asmlinkage long sys_helloworld(void);

Linux内核实验 (内核编译)添加系统调用_第2张图片

添加系统调用id编号

进入/usr/src/linux-4.16.10/arch/x86/syscalls目录,打开文件syscall_64.tbl

cd /usr/src/linux-4.16.10/arch/x86/entry/syscalls
sudo gedit syscall_64.tbl

添加自己的系统调用号

333  64  helloworld           sys_helloworld

Linux内核实验 (内核编译)添加系统调用_第3张图片

注意,这里查看一下自己是64还是32位的,如果不确定可以在syscall_32.tbl里也添加一下


编译内核

依次输入这四条语句

sudo make mrproper 
sudo make clean 
sudo make menuconfig 
sudo make -j2          (根据自己的线程来设置 4核4线程就-j4 线程越多编译越快)

sudo make menuconfig
有的可能会报错,可能是因为窗口太小显示不了图形界面,建议先把窗口最大化
Linux内核实验 (内核编译)添加系统调用_第4张图片
这里直接save保存就好 然后exit退出
make编译的时间超级漫长,大概2到3个小时 可以挂着去干别的了

注意一下,内存空间是否足够,我一开始没有注意到这些问题,用虚拟机编译到最后,磁盘的空间不够了,忍痛删除了一些东西,释放空间,才最后编译安装完成,大家一定要吸取我的教训,磁盘小的话,先做好备份,转移到大的空间在开始编译。

安装内核

简单执行即可,没什么好说的

sudo make modules_install  
sudo make install  

重启虚拟机或系统

reboot

开机时 一直长按shift进入如下画面
选高级选项
Linux内核实验 (内核编译)添加系统调用_第5张图片
在选定我们的内核进入
Linux内核实验 (内核编译)添加系统调用_第6张图片
中途我出现了这样的问题,卡在这个logo上 就是进不去系统
(如果没有这个问题,直接往下看就行了 忽视)

Linux内核实验 (内核编译)添加系统调用_第7张图片
这个问题困扰了我很久,正常不去但是能进去恢复系统,在网上查询也无果,我认为可能是我编译时出现了问题,前前后后又重新编译了几次,花费不少时间,后来一顿瞎操作就进到内核里了,这里写出来,仅供大家参考
如果出现别的问题也请善用百度,我这里也就提出我实验中发现的问题,如果实在不行可以尝试重新编译或者换一下别的版本的内核。
Linux内核实验 (内核编译)添加系统调用_第8张图片
这里选recovery mode 恢复进入
Linux内核实验 (内核编译)添加系统调用_第9张图片
直接选第一个一直ok就进入了

验证系统调用是否成功

进入到系统,查看一下内核
在这里插入图片描述
和我们编译的内核对上了,成功进入

下面编写一个函数,来试试我们自己编写的函数调用

gedit test.c

test.c

#include 
#include 
int main()
{
	syscall(333);		//上面自己定义的系统调用编号
	return 0;
}

编译一下

gcc test.c

Linux内核实验 (内核编译)添加系统调用_第10张图片
因为我们的系统调用函数使用printk打印 会显示在日志上,而不是控制台
我们先清空一下日志 方便观察

sudo dmesg -C	清空日志
dmesg			查看日志

接下来在试试我们自己编写的系统调用吧
Linux内核实验 (内核编译)添加系统调用_第11张图片
成功 调用

实验总结与感受

本来认为是一个简单的小实验,自己上手操作时,会出现各种问题,前前后后也花了不少时间完成,在网上查了不少资料,借鉴大佬的操作流程,站在巨人的肩膀上向前推进。这次实验,新学到了许多关于系统调用的新知识,用户栈到内核栈的转换,系统调用表的查询等。同时,自己也近距离的接触了一下内核,对内核进行一些简单的修改,使高深莫测的内核,变得不再那么遥不可及,熟悉linux的同时,也提升了自己的调试能力和自己的耐心,完成了这个实验。

你可能感兴趣的:(linux,操作系统)