在Linux系统下增加一个自定义的系统调用
操作系统课程的作业,centos系统中编译linux内核,并增加一个自定义的系统调用
前言
操作系统课程的作业,由于刚接触Linux时习惯先获取root身份,建议不这样做,而是合理运用sudo命令。实验平台为VMware虚拟机,系统为CentOS 7
实验过程
1. gcc/g++的安装
(1)为后续操作方便,先获取root权限:
sudo su
(2)直接yum安装的是4.8.5版本的gcc、g++,版本过旧已经无法编译5.11.7版本的内核,因此下载10.2.0版本的gcc,之后解压(国内镜像):
tar -xzvf /home/gcc-10.2.0.tar.gz
(4)配置依赖项:
cd /home/gcc-10.2.0
./contrib/download_prerequisites
(5)创建安装文件夹、编译文件夹:
mkdir /usr/lib/gcc/x86_64-redhat-linux/10.2.0
mkdir /home/gcc-build-10.2.0
(6)配置安装文件:
cd /home/gcc-build-10.2.0
../gcc-10.2.0/configure --prefix=/usr/lib/gcc/x86_64-redhat-linux/10.2.0/ --enable-checking=release --enable-languages=c,c++ --disable-multilib
(7)执行编译&&安装:
make && make install
(8)备份原gcc并链接新gcc:
mv /usr/bin/gcc /usr/bin/gcc-4.8.5
mv /usr/bin/g++ /usr/bin/g++-4.8.5
alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8.5 88 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8.5
alternatives --install /usr/bin/gcc gcc /usr/lib/gcc/x86_64-redhat-linux/10.2.0/bin/x86_64-pc-linux-gnu-gcc 99 --slave /usr/bin/g++ g++ /usr/lib/gcc/x86_64-redhat-linux/10.2.0/bin/x86_64-pc-linux-gnu-g++
alternatives --config gcc
(9)至此,gcc10.2.0版本就安装完成了,查询版本号:
gcc -v
g++ -v
2. 下载、移动并解压内核
(1)先从网页kernel.org下载,我选择的是5.11.7版本(Latest Release),默认的下载路径为/home/用户文件夹/下载:
(2)可以使用mv命令移动,或者为了操作简便使用:
nautilus
这个命令的作用是打开一个具有root权限的文件资源管理器(此前下载gcc时已提到使用sudo su获取权限,故此后的sudo均省去),之后移动至/usr/src
(3)解压:
cd /usr/src
tar -xvf linux-5.11.7.tar.xz
3. 定义系统调用函数
(1)下载vim,用于编辑文本:
yum -y install vim
vim的基本用法:
i 进入输入模式(Insert mode)
Page Up/Page Down 上/下翻页
ESC 退出输入模式
:wq保存并退出(在命令模式下输入)
:q 不保存退出
(2)添加系统调用函数:
vim /usr/src/linux-5.11.7/kernel/sys.c
并在末尾添加自定义函数(参数void不可省略):
asmlinkage long __x64_sys_helloworld(void){
printk("Hello, world!\n");
return 0;
}
(3)设置系统调用号:
vim /usr/src/linux-5.11.7/arch/x86/entry/syscalls/syscall_64.tbl
添加:
442 64 helloworld sys_helloworld
系统调用号可自行设置,不同的内核版本会有所不同。
(4)在系统调用的头文件中定义:
vim /usr/src/linux-5.11.7/include/linux/syscalls.h
添加:
asmlinkage long __x64_sys_helloworld(void);
4. 编译内核
(1)配置内核:
基于文本选单的配置界面,执行:
cd /usr/src/linux-5.11.7
make menuconfig
之后的步骤中因为缺少一些依赖包而报错,按提示安装即可,例如:
yum -y install ncurses-devel
顺利进入界面,感觉没什么需要修改的,直接保存退出:
(2)开始编译(-j后的数字为核心数,提升编译速度):
make -j8
刚开始编译还是根据提示缺什么装什么:
yum -y install elfutils-libelf-devel
yum -y install openssl
yum -y install openssl-devel
继续编译,其实这一步挺不容易的,我之前困在arch/x86/entry/syscall_64.o:(.rodata+xxx):对‘__x64_sys_xxx’未定义的引用
这里,相关资料也不多(这个规定应该是某个版本后更改的),尝试改动又编译失败很多次之后才发现要在声明函数和定义函数前加上__x64_
。
(3)安装内核:
make modules_install
make install
(4)更新启动项:
grub2-mkconfig -o /boot/grub2/grub.cfg
(5)重启:
查看版本:
cat /proc/version
5. 编写用户态函数
vim test.c
插入代码:
#include<sys/time.h>
#include<stdio.h>
#include<unistd.h>
int main(void){
syscall(442);
return 0;
}
编译:
gcc test.c
查看结果:
./a.out
dmesg
dmesg
可查看开机信息。内核中使用的printk()
并不是将消息输出在终端上,而是内核的ring buffer中。
更多推荐
所有评论(0)