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

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

一、实验环境

虚拟机为VMware Workstation,系统为Ubuntu 18.04

编译5.0内核

mkdir LinuxKernel
cd ~/Linuxkernel/
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 i386_defconfig
make -j8

可能的问题

/bin/sh: 1: bison: not found
scripts/Makefile.lib:217: recipe for target ‘scripts/kconfig/zconf.tab.c’ failed
make[2]: *** [scripts/kconfig/zconf.tab.c] Error 127
Makefile:514: recipe for target ‘silentoldconfig’ failed
/bin/sh: 1: flex: not found
scripts/Makefile.lib:202: recipe for target ‘scripts/kconfig/zconf.lex.c’ failed
make[2]: *** [scripts/kconfig/zconf.lex.c] Error 127
Makefile:514: recipe for target ‘silentoldconfig’ failed
error : openssl/bio.h :No such file or folder

解决方案

sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libssl-dev

制作根文件系统

cd ~/LinuxKernel/
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 ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

可能的问题

/usr/bin/ld: 当搜索用于 /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a 时跳过不兼容的 -lgcc
/usr/bin/ld: 找不到 -lgcc
/usr/bin/ld: 当搜索用于 /usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so 时跳过不兼容的 -lgcc_s
/usr/bin/ld: 找不到 -lgcc_s

解决方案

sudo apt install gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib

启动MenuOS

qemu-system-i386 -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img

一切顺利的话,可以看见如下界面
在这里插入图片描述

二、实验过程

跟踪内核启动

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

打开另一个终端

cd LinuxKernel/linux-5.0.1
gdb vmlinux
(gdb) target remote:1234

在这里插入图片描述

实现系统调用

查找系统调用表可知,标号36的系统调用为sync
在这里插入图片描述

函数原型void sync(void)
头文件unistd.h
函数说明sync负责将系统缓冲区的数据“写入”磁盘,以确保数据的一致性和同步性
注意sync函数仅仅是将全部改动过的块缓冲区排入写队列,然后就返回,并不等待实际I/O操作结束

在menu目录下的test.c中增加sync的系统调用:

int Sync(int argc,char *argv[])
{
    sync();  
    printf("Sync has done!\n");    
    return 0;
}
int SyncAsm(int argc,char *argv[])
{
    asm volatile(
	"mov $0x24,%%eax\n\t"
	"int $0x80\n\t"
	"mov %%eax,%0\n\t"
    : "=m"
    );
    printf("SyncAsm has done!\n");
    return 0;
}
int main()
{
	...
	...
	MenuConfig("sync","Make all changes done",Sync);
    MenuConfig("sync-asm","Make all changes done(asm)",SyncAsm);
}

重新编译制作rootfs.img后启动MenuOS
可以进行如下的互动:
在这里插入图片描述

跟踪系统调用

在这里插入图片描述

三、实验总结

系统调用

  • 当调用一个系统调用时,CPU从用户态切换到内核态并开始执行一个system_call和系统调用内核函数。在Linux中通过执行int
  • 0x80来触发系统调用,内核为每个系统调用分配一个系统调用号,用户态进程必须明确指明系统调用号,需要使用EAX寄存器来传递。
  • 系统调用可能需要参数,但是不能通过像用户态进程函数中将参数压栈的方式传递,因为用户态和内核态有不同的堆栈,必须通过寄存器的方式传递参数。
  • EAX用来传递系统调用号,EBX、ECX、EDX、ESI、EDI、EBP用来传递参数,若参数较多,则把指向内存的指针存入寄存器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值