系统调用是用户程序请求操作系统内核执行受保护操作的接口,例如读写文件、创建进程、映射内存或建立 Socket。普通函数调用通常在当前权限级内跳转到另一段代码;系统调用则通过体系结构规定的陷入指令进入内核入口,切换到受保护的执行环境,内核校验参数和权限后完成操作,再把返回值或错误状态交还用户程序。
典型流程包括:用户库把系统调用号和参数放入约定寄存器或内存;执行 syscall、svc 等指令;CPU 保存必要状态并切到内核态和内核栈;内核分派处理函数,访问内核资源或等待 I/O;最后恢复用户态上下文并返回。不同 CPU 架构、ABI 和操作系统的寄存器约定不同,不宜把某一种细节当成通用规则。
系统调用会发生用户态到内核态的转换,但不必然发生进程/线程上下文切换。若调用快速完成,内核可返回同一线程,只有特权级变化;若调用阻塞,调度器才可能让出 CPU 给别的线程,稍后再恢复原线程。反过来,定时器中断可触发调度而不属于用户程序主动发起的系统调用。
库函数也不一定都对应系统调用。有的纯粹在用户态计算;有的封装一次系统调用;有的为提高效率先缓冲数据,只有缓冲区需要填充或刷新时才调用内核。系统调用涉及参数复制、权限检查、陷入/返回和可能的调度,因此频繁小调用可能有成本,但是否是瓶颈应结合测量。
常见追问
Q:用户态程序为什么不能直接读磁盘?
A:直接控制设备和内核数据需要特权权限。程序通过系统调用表达请求,内核检查权限、仲裁共享设备并维护一致状态。
Q:系统调用一定会切换上下文吗?
A:会发生执行权限级转换,但未必切换到另一个线程。上下文切换通常指调度器保存当前可运行实体并恢复另一个实体。
Q:调用 printf 就是一条系统调用吗?
A:不是。printf 是用户态库函数,可能先写入用户态缓冲区;之后 write 等系统调用才把数据交给内核。