引言
系统调用是用户空间程序请求内核服务的唯一受控入口。每次read()、write()、open()的背后,都涉及一次完整的特权级切换——从Ring 3用户态陷入Ring 0内核态,执行完毕后再安全返回。本文从汇编指令层面,逐层剖析这条通路上每一个关键节点。
1. 用户态发起:syscall指令的微观操作
在x86_64架构上,syscall指令替代了传统的int 0x80软件中断。它的执行动作如下(Intel手册定义):
; 用户态执行 syscall 前:
; rax = 系统调用号 (如 __NR_write = 1)
; rdi = 第1参数 (fd)
; rsi = 第2参数 (buf)
; rdx = 第3参数 (count)
syscall ; 原子性地完成:
; 1. RCX = RIP (返回地址)
; 2. R11 = RFLAGS (标志寄存器)
; 3. RIP = IA32_LSTAR (内核入口)
; 4. CS = IA32_STAR[47:32]
; 5. SS = IA32_STAR[47:32] 8
syscall不会保存栈指针(RSP),这是与int指令的关键区别——内核入口必须立即切换栈。
2. MSR寄存器:内核配置的秘密
系统调用的路由信息存储在MSR(Model Specific Register)中,内核在启动时通过wrmsr指令配置:
// arch/x86/kernel/cpu/common.c
void syscall_init(void)
{
wrmsr(MSR_LSTAR, (unsigned long)entry_SYSCALL_64, 0); // 入口点
wrmsr(MSR_STAR, segments, 0); // 段选择子
wrmsr(MSR_FMASK, TF_WORK_SYSCALL|MASK, 0); // 入口屏蔽的RFLAGS位
// MSR_GS_BASE 指向 per-CPU 的 pcpu_hot 结构
wrmsrl(MSR_GS_BASE, (unsigned long)

发表评论 取消回复