提示:本文章是本人课程实验过程中的步骤,若在相同环境下配置应该可以复原整个实验,若有错误欢迎指正!


一、实验环境

PC机1台,Windows操作系统和其上的虚拟Linux操作系统。

注意:本实验基于CentOS74.14.277内核

二、实验准备及步骤

实验准备:到官网或者相关下载点下载内核源代码linux-4.14.277.tar.gz把源码移动到/usr/src/目录下,然后解压,目录linux-4.14.277里的内容就是版本4.14.277的内核源码树。

1.查看系统当前内核版本

开发之前首先得确定系统的内核版本是哪一个,可以通过uname -r来查看
在这里插入图片描述

2.安装内核源码

1.使用wget命令到kernel官网下载内核源码(https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.14.277.tar.xz)

在这里插入图片描述
2.解压

在这里插入图片描述

解压后显示如下:
在这里插入图片描述

3.添加新函数

在/usr/src/linux-4.14.277/kernel/sys.c中,添加一个系统调用函数到内核,命名和功能如下:
compat_sys_mysyscall()。在现有的系统中添加一个不用传递参数的系统调用,调用这个系统调用,使用户的uid变成0。

1.编辑sys.c文件

在这里插入图片描述

2.编辑结果如下(shift+g跳转到文末后编写系统调用函数):

在这里插入图片描述

asmlinkage说明参数传递不是靠寄存器,而是靠栈来传递。

然而,这样编写函数在后面编译内核时报错了,由于版本问题,CentOs7的task_struct中没有uid这个变量:
在这里插入图片描述

经过查询task_struct的定义后,修改编写的系统调用函数为:
在这里插入图片描述

4.更新头文件

在/usr/src/linux-4.14.277/include/linux/syscalls.h中,添加系统调用号,如下图所示:
1.编辑syscalls.h

在这里插入图片描述

2.编辑结果如下:

在这里插入图片描述

5.更新系统调用表

1.修改/usr/src/linux-4.14.277/arch/x86/entry/syscalls/syscall_64.tbl文件

在这里插入图片描述

2.编辑结果如下,其中<548为增加的系统调用号,mysyscall为调用函数名,common为abi,compat_sys_mysyscall为程序入口>

在这里插入图片描述

6.重新编译内核

1.安装必备组件

要在CentOS 7上从源代码处编译Linux内核,必须在CentOS 7操作系统上安装一个构建工具和一些其他软件包。

----- [ 1 ] 在安装任何内容之前,运行以下命令以更新包缓存:

在这里插入图片描述

----- [ 2 ] 使用以下命令安装编译内核所需的编译器和库:

  • yum install ncurses-devel make gcc bc openssl-devel

在这里插入图片描述

  • yum install elfutils-libelf-devel

在这里插入图片描述

  • yum install rpm-build

在这里插入图片描述

2.重新编译内核
----- [ 1 ] 复制原本内核的配置文件

在这里插入图片描述

----- [ 2 ] 配置内核选项,采用默认配置即可

在这里插入图片描述
在这里插入图片描述

----- [ 3 ] 编译,令8核一起编译加快速度(此过程时间较长,计算机性能较好可以令尽可能多的内核一同编译)

在这里插入图片描述

----- [ 4 ] 安装内核

编译只是把源码变成可执行文件,但目前为止,这些可执行文件并没有被放置到相应的目录下,新内核也没有注册给引导程序。所以接下来执行以下操作:

  • 1)安装模块

在这里插入图片描述

执行完这条命令,内核模块的可执行文件会被copy到/lib/modules/下,进入这个目录可看到有一个名为4.14.277的文件夹,这里面便是这个内核模块的可执行文件。

  • 2)注册启动项

在这里插入图片描述

这个命令是将该内核注册给引导程序,当开机启动的时候,引导程序会调用注册给它的内核来启动系统,如果有多个内核,用户可以选择从哪个内核启动。

----- [ 5 ] 重启
至此,新内核已经‘安装’在了系统中,只需输入reboot,重启一下系统,用新内核引导。

# reboot

在这里插入图片描述

三、实验记录及数据处理

1.编辑测试程序test.c如下:

在这里插入图片描述

2.运行结果如下:

在这里插入图片描述

因为系统调用的printk不会打印在基本输出上,所以我们在sys.c中实现的printk效果不会打印出来,但是我们可以使用dmesg查看内核态打印的信息(由于直接使用dmesg显示的信息过多,所以可以使用dmesg | tail -5来筛选出548号系统调用函数的结果)。

在这里插入图片描述


四、实验中的问题及解决方法

  • 问题1.编译内核时缺少相关包使得内核无法编译

在这里插入图片描述

查阅资料后发现编译内核之前需得安装好编译所需要的相关包。

  • 问题2.虚拟机设置的相关问题

------ 1)根据主机的情况将虚拟机设置为8核,方便提高‘make’的执行速度;

在这里插入图片描述

------ 2)扩展磁盘容量,不然在时会出现空间不足的情况(如下所示):

在这里插入图片描述

修改虚拟机容量为60GB,然后进入虚拟机对磁盘分区进行重新划分(虚拟机内部的磁盘分区也要再次划分,对/boot部分的容量进行适当的增大):

在这里插入图片描述
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐