系统调用¶
Overview¶
好, 我最近感觉效率太低了, 于是想先写一点文档再开始写代码...
2 ways¶
- soft int (x86)
- sysenter / sysexit (syscall / sysret)
一般而言, 后者的实现更加高效, 我选择先实现前者
中断的方式在 64 位 linux 下并不推荐, 这里使用是为了实验, 使用 syscall 的传参
soft int¶
在这之前需要先 设置 tss, 要不然从 用户态 回到 内核态就不知道该用哪个栈了
sysenter / sysexit¶
这两个指令提供了一个比 中断 更加快速的方法访问内核.
在使用这些指令之前我们需要进行一些初始化工作.
MSR 寄存器:
IA32_SYSENTER_CS- 0x174IA32_SYSENTER_ESP- 0x175IA32_SYSENTER_EIP- 0x176
在 32位 下, 后两个寄存器是 32bit, 在 64位 下, 它们被扩展到 64bit.
syscall / sysret¶
kern_cs = IA32_STAR[47:32]kern_ss = IA32_STAR[47:32] + 8user_cs = IA32_STAR[63:48] + 16user_ss = IA32_STAR[63:48] + 8user32_ss = IA32_STAR[63:48]
the reason for use of the layout?
USER32 / USER64 -> compact / long mode 也就意味着 gdt 布局变成这样
- syscall invoked
load rip -> rcxrflags &= IA32_FMASKload cs / ss
- sysret invoked
load r11 -> eflagsload cs / ssload rcx -> rip(ret to long mode)load ecx -> rip(ret to compact mode)
register usage¶
man syscall
syscall nr¶
cat /usr/include/asm/unistd_64.h
SYS___NR_
references¶
- man
- sysenter | osdev