← 前一天目录后一天 →

每日科普 · 2026-11-02 周一

考研 408 × 求职面试

知识点 · 操作系统 · 进阶

系统调用的执行过程与参数传递

系统调用是用户程序请求操作系统内核服务的受控入口。执行过程可概括为: 1. 用户态准备:按 ABI 把系统调用号放入约定寄存器(如 x86-64 Linux 用 rax),参数放入 rdi、rsi、rdx、r10、r8、r9,超过 6 个参数通常放到内存并由寄存器传指针。 2. 陷入内核:执行 syscall(或 int 0x80)触发特权级切换,CPU 保存返回地址和标志,跳到内核入口。 3. 内核处理:保存用户上下文,检查调用号,查系统调用表找到服务例程,把用户参数安全拷贝/校验后执行,可能阻塞或调度。 4. 返回用户态:结果放回 rax,恢复现场并执行 sysret/iret;若出错常用负 errno 表示,用户库再设置 errno。 参数传递核心是 ABI 约定:少量参数用寄存器,多参数用栈/内存指针;内核不能直接信任用户指针,需 copy_from_user 等机制。与普通函数调用不同,系统调用跨越特权级,开销更大。

每日一题 · 操作系统

系统调用的执行过程与参数传递

在 Linux x86-64 中执行 write(fd, buf, len) 系统调用时,参数传递和调用号位置通常是? A. 参数压栈,调用号放 eax B. 调用号放 rax,前三个参数依次放 rdi、rsi、rdx,再用 syscall C. 调用号放 rdi,参数放 rax D. 全部参数由内核从用户栈直接读取,无需寄存器

解析

答案 B。x86-64 Linux 的系统调用约定是:rax 放系统调用号,rdi、rsi、rdx、r10、r8、r9 依次传前六个参数,超过部分放内存。用户态执行 syscall 陷入内核后,内核保存现场、按 rax 查系统调用表并分派,参数从寄存器或用户内存安全拷贝,返回值放 rax。因此 write 的 fd、buf、len 分别放 rdi、rsi、rdx。

面试小贴士 · 操作系统

系统调用的执行过程与参数传递

面试常问执行流程、参数如何传、与函数调用区别。答:用户态按 ABI 准备调用号与参数→陷入→内核保存现场、查表分派、执行并返回;参数多用寄存器,超限用内存,用户指针需校验/拷贝。易错:syscall 不是普通函数、返回值与 errno、寄存器约定。

代码实现 · C

代码示例

#include <stddef.h>

int main(void) {
    const char msg[] = "hello syscall\n";
    long ret;
    // x86-64 Linux:rax=1(write),rdi=fd,rsi=buf,rdx=len
    __asm__ volatile(
        "mov $1, %%rax\n"
        "mov $1, %%rdi\n"
        "mov %1, %%rsi\n"
        "mov %2, %%rdx\n"
        "syscall\n"
        : "=a"(ret)
        : "r"(msg), "r"(sizeof(msg) - 1)
        : "rdi", "rsi", "rdx", "rcx", "r11", "memory"
    );
    return ret == (long)(sizeof(msg) - 1) ? 0 : 1;
}
← 前一天目录后一天 →