用户程序,以write(1,"hello",5);为例步骤2:执行syscall指令,触发内核调用(用户态->内核态)用户程序执行汇编指令 syscall(64 位专属特权指令):
- 这个指令直接向 CPU 发送 “请求切换到内核态” 的信号,比 32 位
int 0x80更高效(无中断处理的冗余开销); - 这是整个流程的 “开关”,执行完这条指令,CPU 就开始准备切换特权级。
步骤 3:CPU 切换到内核态,保存用户态现场(CPU + 内核)1,特权级切换:从用户态(Ring3,低特权,不能操作硬件 / 内核内存)切换到内核态(Ring0,高特权,可访问所有资源);- 把用户态的程序计数器(
rip,记录下一条要执行的指令地址)存入 rcx 寄存器; - 把用户态的标志寄存器(
rflags)存入 r11 寄存器; - 内核会把这些寄存器值 + 用户态其他寄存器(如
rdi/rsi)保存到内核栈中(目的:处理完能精准回到用户程序原来的位置)。
1,内核有一张系统调用表(sys_call_table),表里存储了所有系统调用的处理函数地址(比如sys_write对应write,sys_exit对应exit)2,内核根据rax中的数值,从表中找到对应的函数->内核确认要办什么事情,避免调错逻辑1,成功:返回操作结果(例如write返回实际写入的字节数,read返回读取的字节数)2,失败:返回负数错误码(比如 - 1),并在内核中记录errno(用户态程序可通过perror()等函数查看具体错误)。步骤7:内核恢复用户态现场,切换回到用户态(内核+CPU)内核从内核栈中取出步骤 3 保存的用户态数据,完成 “返程准备”:
- 把
rcx中保存的用户态rip恢复到 CPU 的程序计数器; - CPU 执行
sysret指令(syscall的配套指令),从内核态(Ring0)切回用户态(Ring3);→ 这一步完成后,CPU 的特权级回到用户态,且记住了用户程序该继续执行的位置。
CPU回到用户程序中,从syscall指令的下一条指令开始执行1,用户程序读取rax寄存器中的返回值,判断系统调用是否成功