学号272原创作品

转载请注明出处 https://github.com/mengning/linuxkernel/

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

一,实验过程

  • 1,实验目的
    • 1.编译内核5.0
    • 2.选择系统调用进行跟踪分析
  • 2,实验准备
    • 1,VMware Workstation Pro
    • 2,Ubuntu 18.04 虚拟机
  • 3,编译内核5.0

a,下载linux5.0内核版本

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.0.tar.xz

结果如下:

01patch

b,解压编译

xz -d linux-5.0.1.tar.xz tar -xvf linux-5.0.1.tar cd linux-5.0.1 make i386_defconfig

在这里遇到如下问题:

01patch

分析:这里缺少了必须的文件,根据提示解决指令下载对应数据flex和bison

sudo apt-get install flex sudo apt-get install bison

编译文件

make i386_defconfig make

在这里遇到如下问题:

qemu

分析:这里确实一个libssl-dev,直接安装即可

sudo apt-get install libssl-dev

c,制作根文件系统,从孟老师github上下载内核文件

sudo apt-get install gcc-multilib

cd .. mkdir rootfs git clone https://github.com/mengning/menu.git cd menu gcc -pthread -o init linktable.c menu.c test.c -m32 -static cd ../rootfs cp ../menu/init ./

d,编译

qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img -s -S -append nokaslr

e,内核跟踪调试,重新编译Linux内核

make menuconfig

提示:若窗口太小可能会报错

f,跟踪调试内核启动

qemu -kernel linux-5.0/arch/x86/boot/bzImage -initrd rootfs.img -s -S -append nokaslr

g,使用gdb打开调试工具

gdb (gdb)file linux-5.0/vmlinux (gdb)target remote:1234

结果

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

本人学号后三位272,所以根据学号后两位进行系统调用

说明:pause()会令目前的进程暂停(进入睡眠状态),直至信号(signal)所中断。 返回值:只返回-1 于是修改test.c中的代码,添加一个调用pause的代码

#include <signal.h>
#include <unistd.h>
void sigl_name(int num)
{
    printf("receive the signal %d.\n", num);
    alarm(2);
}
int Pause_test(int argc, char *argv[])
{
    signal(SIGALRM, 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);
    ExecuteMenu();
}

程序结果分析,pause会使当前的进程进入睡眠状态,直到我们由定时器alarm向该 signal发送SIGALRM信号,进程才会被唤醒,并处理信号,处理完信号后pause函数才返回,并继续运行该程序,具体情况如下图所示:

分析:一步步执行下来可以看出具体流程sys_pause->schedule->sys_pause->do_fast_syscall_72 ->entry_sysenter_72->entry_int80_72

二,实验总结

  • 1,总结

对于linux的系统调用过程有了新理解

用户程序——>C库(即API):INT 0x80 ——>system_call——>系统调用服务例程——>内核程序

系统调用分析

1,系统中的调用,就是通过系统调用号来给这些system_call来编号,不同功能给予不同的功能号,如这次使用的就是29号 Pause功能,通过这样让系统明确知道用户想要执行的是哪个系统调用。而这之间的传递主要是通过eax寄存器来传递

2,系统调用主要就是一种用户态到内核态最后再到用户态的一种过程,用户态可以说成间接操作内存的程序,而内核态也就是通过汇编代码直接操作内存,而他们再转换过程中,由于涉及上下文的切换问题,所以需要对内容进行保护,所以再进入中断程序前,将内核态寄存器的值放入栈中,在程序结束后再进行出栈

  • 2,心得

通过本次实验,初步解除了Linux系统的编译和系统调用的过程,但是因为对linux的使用比较少,对于其工作原理的理解还不够深入,还需要通过课上课下的结合加深对linux的熟悉度