深入理解Linux系统调用

1、系统调用号查询

我的学号位数是08,在64位调用表里可以查到对应的系统调用函数是__x64_sys_lseek

深入理解Linux系统调用_第1张图片

2、lseek函数

由于没用过该函数,所以先去了解一下这个函数的作用:

深入理解Linux系统调用_第2张图片

 

 直白的说就是用来移动文件指针,演示一下(c语言调用lseek库函数)

深入理解Linux系统调用_第3张图片

 可以看到图片里我输出了两次a.txt文本里的内容

第一次是从头开始输出的,第二次这是将指针从开头移动了30个位移量,返回结果result 也为30,输出的结果自然也和第一次不一样了。

 

3、汇编语言调用

深入理解Linux系统调用_第4张图片

 

 

 

在64位系统中,参数的传递不再使用ebx ecx edx等寄存器了

而是使用rdi、rsi、rdx寄存器传递参数,

rdi传递第一个参数file,也就是文件描述符,%1表示第一个输入,表示后面的"m"(file)

rsi传递第二个参数offset,我直接设置成了30

rdx传递第三个参数position,传入0表示从文件开始开始移动

后传入系统调用号0x08至eax,并执行syscall

结果返回至result变量中

 

4、gdb调试和分析

由于要在内核下进行调试分析,所以得使用busybox为内核制作一个根文件系统

并将c文件使用静态编译后

gcc -o myfile myfile.c -static

放入rootfs/home下,以便后续执行

深入理解Linux系统调用_第5张图片

 

 

 

接着先开启一个terminal,输入命令:

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

然后在开启一个terminal,依次输入

gdb vmlinux

target remote:1234

如图,并打上断点:

b __x64_sys_lseek

深入理解Linux系统调用_第6张图片

可以看到这个函数在fs/read_write.c文件里的第322行,用vscode打开查看下函数

深入理解Linux系统调用_第7张图片

可以看见有两个SYSCALL_DEFIND3和一个SYSCALL_DEFIND5,都是lseek相关的

但本次使用的是第322行的SYSCALL_DEFIND3调用(跟后面并无太大区别,后面的SYSCALL_DEFIND3只是使用了宏,有使用条件)

随后执行ksys_lseek函数,该函数执行:

1、检查文件标识符是否存在,其次调用vfs_llseek(....args)函数开始移动文件指针

vfs_llseek(....args)函数如下:

深入理解Linux系统调用_第8张图片

最后返回一个off_t类型的retval结果,off_t在linux64位下即long int类型

从代码中我们可以看出,如果偏移量没有超出文件范围或者第三个参数位置传递无误的话

返回的retval刚好等于我们移动的指针偏移量

深入理解Linux系统调用_第9张图片

 

在前面的运行结果中也刚好等于30

接着我们运行home文件夹下的myfile可执行文件

深入理解Linux系统调用_第10张图片

可以看到并没有任何输出,被阻塞在了SYSCALL_DEFINE3函数调用上

我们可以使用n 命令单步执行, bt查看堆栈

深入理解Linux系统调用_第11张图片

 

可以看到程序先去执行了entry_syscall_64函数

后common.c下执行了do_syscall_64函数

最后随着两个popq出栈指令,恢复了rdirsp寄存器,系统调用完成。

 

先来到entry_64.S文件

深入理解Linux系统调用_第12张图片

它在保存上下文信息和传递完参数后随即去执行do_syscall_64

 

接着去common.c中查看下do_syscall_64函数做了什么

深入理解Linux系统调用_第13张图片

可见它在sys_call_table表中拿到系统调用号后存入regs->ax中,后开始执行系统调用

也就是执行read_write里面的SYSCALL_DEFIND3,调用lseek移动文件指针

执行完后又回到do_syscall_64函数中,接下来要执行的 syscall_return_slowpath 函数要为恢复现场做准备。

 

 

执行完后又回到上一层的堆栈即entry_syscall_64函数

深入理解Linux系统调用_第14张图片

 

 继续在vscode中查看entry_syscall_64后续的代码

深入理解Linux系统调用_第15张图片

可见后续的代码是在完成执行现场的恢复

最后的两个popq出栈指令恢复原 rdi 和 rsp的内容,也就是完成了堆栈的切换。

至此系统调用完成。

你可能感兴趣的:(深入理解Linux系统调用)