C 系统调用API、系统调用指令和异常机制(中断)之间的关系
我试图理解C 系统调用API、系统调用指令和异常机制(中断)之间的关系,c,linux,assembly,operating-system,x86-64,C,Linux,Assembly,Operating System,X86 64,我试图理解C语言系统调用API、syscall汇编指令和用于在进程之间切换上下文的异常机制(中断)之间的关系。我有很多东西要自己学习,所以请容忍我 我的理解正确吗?C语言系统调用由编译器以syscall的形式实现,其各自的代码在汇编中,然后由操作系统以异常机制(中断)的形式实现 因此,在下面的Ccode中调用write函数: #include <unistd.h> int main(void) { write(2, "There was an error writing t
C
语言系统调用API、syscall
汇编指令和用于在进程之间切换上下文的异常机制(中断)之间的关系。我有很多东西要自己学习,所以请容忍我
我的理解正确吗?C
语言系统调用由编译器以syscall
的形式实现,其各自的代码在汇编中,然后由操作系统以异常机制(中断)的形式实现
因此,在下面的C
code中调用write
函数:
#include <unistd.h>
int main(void)
{
write(2, "There was an error writing to standard out\n", 44);
return 0;
}
反过来,该指令是由操作系统作为异常机制(中断)来实现的?不是对这个问题的直接回答,但这可能会引起您的兴趣(我没有足够的理由来评论)-它详细解释了所有用户空间执行(包括glibc及其如何进行系统调用): 您可能会对“步骤8-写入标准输出的最终字符串”特别感兴趣: 那么uu libc_uwrite看起来像什么
000000000040f9c0 <__libc_write>:
40f9c0: 83 3d c5 bb 2a 00 00 cmpl $0x0,0x2abbc5(%rip) # 6bb58c <__libc_multiple_threads>
40f9c7: 75 14 jne 40f9dd <__write_nocancel+0x14>
000000000040f9c9 <__write_nocancel>:
40f9c9: b8 01 00 00 00 mov $0x1,%eax
40f9ce: 0f 05 syscall
...cut...
0000000000 40F9C0:
40f9c0:83 3d c5 bb 2a 00 cmpl$0x0,0x2ABC5(%rip)#6bb58c
40f9c7:75 14 jne 40f9dd
0000000000 40F9C9:
40f9c9:b8 01 00 mov$0x1,%eax
40f9ce:0f 05系统调用
……切。。。
Write只检查线程状态,假设一切正常,
将写入系统调用号(1)移入EAX并进入内核
一些注意事项:
- x86-64 Linux写系统调用为1,旧x86为4
- rdi指标准输出
- rsi指向字符串
- rdx是字符串大小计数
syscall
指令本身就像一个美化的跳转,它是一种硬件支持的方式,可以高效、安全地从非特权用户空间跳转到内核中。syscall
指令跳转到分派调用的内核入口点
在x86_64之前,还使用了另外两种机制:int
指令和syscenter
指令。它们有不同的入口点(目前仍然存在于32位内核中,64位内核可以运行32位用户空间程序)。
前者使用x86中断机制,可能与异常调度(也使用中断机制)混淆。
然而,异常是虚假事件,而
int
用于生成软件中断,再次是美化的跳转
C语言本身并不关心系统调用,它依赖于执行与未来程序环境的所有交互 C运行时通过特定于环境的机制实现上述交互。
可能有不同的软件抽象层,但最终会调用操作系统API 该术语用于表示契约,严格来说,使用API不需要调用一段内核代码(趋势是在用户空间中实现非关键函数以限制可利用的代码),这里我们只对需要特权切换的API子集感兴趣 在Linux下,内核公开了一组可从用户空间访问的服务,这些入口点被称为。
在下面
000000000040f9c0 <__libc_write>:
40f9c0: 83 3d c5 bb 2a 00 00 cmpl $0x0,0x2abbc5(%rip) # 6bb58c <__libc_multiple_threads>
40f9c7: 75 14 jne 40f9dd <__write_nocancel+0x14>
000000000040f9c9 <__write_nocancel>:
40f9c9: b8 01 00 00 00 mov $0x1,%eax
40f9ce: 0f 05 syscall
...cut...
; write(2, "There was an error writing to standard out\n", 44);
mov $44, %edx
lea .LC0(%rip), %rsi ; address of the string
mov $2, %edi
call write