Ale*_*x B 30 c linux performance system-calls
一些(很多?全部?)64位1 Linux发行版允许通过提供32位和64位库(包括libc)的并行集合来运行32位应用程序.因此,32位应用程序可以链接到32位库,并由64位内核运行.
我想知道力学的32位应用程序如何让在64位内核的系统调用.我怀疑答案是在libc和/或内核源代码中的某个地方,但由于我不知道在哪里查看,因此潜入源代码会非常耗时.
还有一个更重要的问题,是否有任何性能开销?2从逻辑上讲,来自32位app系统调用的调用必须转换为64位内部内核环境.这完成的方式和地点?
1 "32位"= IA-32,"64位"= AMD64
2在你的回答中假设它很重要:)
caf*_*caf 27
从用户空间方面来看,这些机制与在32位本机内核上进行系统调用相同 - 所有用户模式代码(包括32位glibc)都以相同的方式工作.
从内核端,用户空间(例如int 0x80)的旧IA32入口点被设置为调用ia32_syscall汇编程序例程.(转换到内核空间涉及处理器加载内核的代码段选择器,这会导致转换到64位"长"模式).
该ia32_syscall例程然后将一些参数混合以匹配x86_64系统调用约定:
movl %edi,%r8d
.if \noebp
.else
movl %ebp,%r9d
.endif
xchg %ecx,%esi
movl %ebx,%edi
movl %edx,%edx /* zero extension */
Run Code Online (Sandbox Code Playgroud)
然后它使用IA32系统调用号通过表进行函数调用ia32_sys_call_table.这基本上将IA32系统调用号与本机系统调用实现相匹配(系统调用号在IA32和x86_64之间差别很大).该表的第一部分如下所示:
ia32_sys_call_table:
.quad sys_restart_syscall
.quad sys_exit
.quad stub32_fork
.quad sys_read
.quad sys_write
Run Code Online (Sandbox Code Playgroud)
对于大多数系统调用,现在可以直接调用x86_64实现 - 就像exit().对于其他人,例如fork(),提供了一个正确实现预期的IA32语义的包装器(特别是,如果需要从32位到64位的参数的符号扩展).
正如您所看到的,内核代码的开销很小 - 对寄存器值进行了一些微不足道的修改,对于一些函数,还有一个额外的函数调用.我不确定加载导致从32位模式转换到64位模式的代码段选择器对于处理器执行的速度比不执行的速度慢 - 请检查处理器体系结构手册.