Linux内核系统调用分析

学号531
原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/

实验:举例跟踪分析Linux内核5.0系统调用处理过程

实验要求

熟悉Linux操作系统的构造、Linux内核5.0 源代码
Build a Linux system, 参考MenuOS
Linux内核的启动过程, 跟踪分析Linux内核的启动过程
熟悉系统调用
glibc提供的系统调用函数API
int 0x80、系统调用号及参数传递过程
保护现场与恢复现场
系统调用内核处理函数
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
分析system_call中断处理过程

实验过程

1.下载Linux内核5.0内核代码,并配置编译Linux内核

mkdir LinuxKernel

下载内核源码:Linux内核5.0 source code并解压到LinuxKernel目录下

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

编译

2.文件系统制作
制作根文件系统

1 mkdir rootfs
2 git clone https://github.com/mengning/menu.git
3 cd menu
4 gcc -pthread -o init linktable.c menu.c test.c -m32 -static
5 cd ../rootfs
6 cp ../menu/init ./
7 find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
  1. 启动MenuOS
qemu-system-i386 -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img

在这里插入图片描述

gdb 
(gdb)file linux-5.0.1/vmlinux # 在gdb界面中targe remote之前加载符号表 
(gdb)target remote:1234 #  
(gdb)break start_kernel # 

在gdb界面中targe remote之前加载符号表
建立gdb和gdbserver之间的连接,
按c 让qemu上的Linux继续运行
设置断点

选择系统调用进行跟踪分析

找到我的学号对应的调用号31.在
/usr/include/asm/unistd_32.h中可查得
在这里插入图片描述
由于stty比较复杂,决定选取序号为29的函数pause进行相应的分析。
真正目的就是进入睡眠,如nanosleep()和pause();

而pause()也是将当前进程进入睡眠,可是与时间无关,要接收到一个信号时才会被唤醒,所以常常用来协调若干进程的运行;它要在接收到特定信号SIGCHLD并且满足若干特殊条件时才会被唤醒;

在sys_pause()中,直接改变运行状态为TASK_INTERRUPTIBLE,然后执行调度schedule();只有接受到信号时才会被唤醒;

自己编写mytest代码,在其中添加一个调用pause的代码。

#include <signal.h>
#include <unistd.h>
void signal_name(int num)
{
	printf("receeive the signal %d.\n",num);
	alarm(2);
}
int Pause_test(int argc, char *argv[])
{
signal(SIGNARM, sigl_name);
alarm(2);
while(1){
		pause();
		printf("pause is over.\n");
		}
		return 0;
}
int main()
{
	PrintMenuOS();
	SetPrompt("MenuOS>>");
	MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6),NULL");
	MenuConfig("quit","Quit from MenuOS",Quit);
	MenuConfig("time","Show System Time",Time);
	MenuConfig("time-asm","Show System Time(Asm)",TimeAsm);
	MenuConfig("pause","Show pause",Pause_test);
}

执行效果:

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

实验总结

系统调用的工作机制是:当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数,由API、中断向量和中断处理程序协调完成。

进程在pause的作用下暂停了,再次感知到信号后才会重新工作。
系统调用的实现:通过系统调用号来给system_call来编号,不同功能给予了不同的功能号。
如这次使用的就是 Pause功能,这样能让系统明确知道用户想要执行的是哪个系统调用。
除了系统调用号外,系统调用也可能需要传递参数,系统调用由于是从用户态到内核态,两者的栈堆不一样,所以他们之间只能由寄存器来进行传递值。进程号是由eax寄存器存储的,参数一般是由ebx、ecx、edx、esl、edl、ebp来存储的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值