跟踪分析Linux内核系统调用处理过程
学号245。原创作品,转载请注明出处:https://github.com/mengning/linuxkernel/
实验要求
举例跟踪分析Linux内核5.0系统调用处理过程
编译内核5.0
qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img
选择系统调用号后两位与您的学号后两位相同的系统调用进行跟踪分析
给出相关关键源代码及实验截图,撰写一篇博客(署真实姓名或学号最后3位编号),并在博客文章中注明“原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ ”,博客内容的具体要求如下:
- 题目自拟,内容围绕系统调用进行;
- 博客中需要使用实验截图
博客内容中需要仔细分析系统调用、保护现场与恢复现场、系统调用号及参数传递过程
总结部分需要阐明自己对系统调用工作机制的理解。
环境配置
编译内核
下载内核5.0并解压
mkdir kernel
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.0.1.tar.xz
xz -d linux-5.0.1.tar.xz
tar -xvf linux-5.0.1.tar
cd linux-5.0.1
make menuconfig //kernel hacking -> Compile-time checks and compiler options [*]compile the kernel with debug info
make
过程中需要手动安装部分依赖。
制作根文件系统
按照如下步骤
cd ..
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
sudo apt install gcc-multilib
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc | gzip -9 > ../rootfs.img
MenuOS
启动MenuOS
qemu-system-i386 -kernel bzImage -initrd rootfs.img
正常启动后如下图所示:
跟踪系统调用
选择学号后两位的系统调用,我的是45,如图所示:
__NR_brk:brk()和sbrk()改变程序间断点的位置。程序间断点就是程序数据段的结尾。(程序间断点是为初始化数据段的起始位置。通过增加程序间断点进程可以更有效的申请内存 。当addr参数合理、系统有足够的内存并且不超过最大值时brk()函数将数据段结尾设置为addr,即间断点设置为addr。sbrk()将程序数据空间增加increment字节。当increment为0时则返回程序间断点的当前位置。
brk()成功返回0,失败返回-1并且设置errno值为ENOMEM。sbrk()成功返回之前的程序间断点地址。如果间断点值增加,那么这个指针(指的是返回的之前的间断点地址)是指向分配的新的内存的首地址。如果出错失败,就返回一个指针并设置errno全局变量的值为ENOMEM。
在test.c中添加如下部分,重新编译制作rootfs.img,观察实验结果。
int err = brk(old);
if(-1 == err){
perror("brk");
exit(EXIT_FAILURE);
}
我这里cpu出了点问题,实验结果不上图了。
总结
当一个系统调用发生的时候,进入内核处理这个系统调用,由内核提供服务,当这个服务结束返回到用户态之前,即在系统调用返回之前,有可能发生进程调度(call schedule),进程调度的里边就会发生进程上下文的切换。
把内核可以抽象成很多种不同的中断处理过程的集合。这样保证了系统的安全性,也为使用者提供了方便。