学号379原创作品转载请注明出处
本实验来源 https://github.com/mengning/linuxkernel/
实验要求
编译内核5.0
qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img
选择系统调用号后两位与您的学号后两位相同的系统调用进行跟踪分析
https://github.com/mengning/menu
给出相关关键源代码及实验截图,撰写一篇博客(署真实姓名或学号最后3位编号),并在博客文章中注明“原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ ”,博客内容的具体要求如下:
题目自拟,内容围绕系统调用进行;
博客中需要使用实验截图
博客内容中需要仔细分析系统调用、保护现场与恢复现场、系统调用号及参数传递过程
总结部分需要阐明自己对系统调用工作机制的理解。
编译Linux内核
下载内核源码git clone https://github.com/mengning/linux.git
解压后 cd linux-5.0
kernel的配置选项十分多,因此全部都自己配置显然是不可能的,可以通过一些默认配置文件进行配置make i386_defconfig(不同的架构不同,这是x86平台的)
make menuconfig设置一些编译选项
进入kernel hacking
在编译的过程中提示编译信息,主要是为了编译过程中可以看到少了什么东西就下载什么东西。
然后可以直接开始make了,可能会报错,但由于之前设置了compile the kernel with debug info,故根据报错信息下载需要的文件即可,整个编译完大概需要十多分钟。
搭建menuOS
编译内核当然是为了能在运行程序时跟踪内核代码,关于qume的配置请参照上篇博客 https://blog.csdn.net/weixin_43822397/article/details/88428585
//制作根文件系统
cd ~/LinuxKernel/
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -o init linktable.c menu.c test.c -m32 -static –lpthread # 系统会默认启动init,即第一个用户态进程,1号进程
cd …/rootfs
cp …/menu/init ./ #拷贝
find . | cpio -o -Hnewc |gzip -9 > …/rootfs.img # 镜像
来源于pianogirl123 https://blog.csdn.net/pianogirl123/article/details/50866778
系统调用的代码
我学号尾数对应的系统调用函数是settimeofday
#include<stdio.h>
#include<sys/time.h>
#include<unistd.h>
int main()
{
struct timeval tv;
struct timezone tz;
int status;
gettimeofday(&tv,&tz);
printf("tv_sec:%d\n",tv.tv_sec); //second
//printf("tz_minuteswest:%d\n",tz.tz_minuteswest);//offset from universal time
tv.tv_sec+=1000000;
//tz.tz_minuteswest+=1000000000;
printf("tv_sec:%d\n",tv.tv_sec);
const struct timval* ta;
const struct timezone* tb;
ta=&tv;
tb=&tz;
status=settimeofday(ta,tb); //reset time
printf("%d\n",status); //0 for success
gettimeofday(&tv,&tz);
printf("tv_sec after_reset:%d\n",tv.tv_sec);
//printf("tz_minuteswest:%d\n",tz.tz_minuteswest);
return 0;
}
这是设置系统时间的代码,执行的时候需要sudo,将它集成到/menu/test.c中,然后就可以打开qemu使用gdb跟踪内核代码了
打开qemu
qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img -s -S -append nokaslr
再打开另外一个terminal窗口输入gdb
file linux-5.0/vmlinux
target remote:1234
接下来就可以打断点调试程序了我们先从start_kernel开始
start_kernel顾名思义就是启动内核,输入l可以看到里面的内容也多是各种初始化
我使用的系统调用函数是settimeofday,而它的entry point是sys_settimeofday,所以我在sys_timeofday处加上一个断点
然后continue,在menuOS中运行这个函数(我之前写好集成在menuOS中的函数,至于集成方法及menuOS代码请参考 https://github.com/mengning/menu)
断点停留在这了,我们看一下上下文
看到systemcall的字眼说明这是系统调用的过程,继续输入n看接下来的步骤
这里出现的handles int $0x80,说明下一步要调用system_call了,系统会进入内核态继续n
继续n
系统通过中断进入内核态之前的一些保护现场的工作,以便回到用户态后恢复用户态时堆栈的内容和寄存器的内容。
总结
参考内容及此图片来源:系统调用system_call的处理过程