操作系统

系统调用:程序怎样请内核帮忙

程序不能直接碰硬件,想读写文件、上网、打印,都得通过“系统调用”这扇门请内核代办。

概况

以 Linux(x86-64)上一个程序往终端打印一行字为例。

一句话总结
系统调用是程序进入内核的唯一受控入口
为什么需要
保护硬件和其他程序,不让一个程序为所欲为
两种模式
用户态(权限受限)和内核态(完全权限)
常见系统调用
read、write、openat、clone、execve、mmap
代价
每次进出内核都有开销,所以要尽量批量处理
出错时
返回 -1,原因在 errno(如 ENOENT、EACCES)
vDSO
clock_gettime 等调用通常不进内核
系统调用表
内核按调用号查表,找到对应的处理函数;调用号是 ABI 的一部分,不随便改

步骤 7 / 7

不进内核的“系统调用”:vDSO

有些只读的小请求,内核干脆把答案放到用户态,省掉一趟切换。

像“现在几点”这种调用非常频繁,每次都陷入内核太亏。 Linux 把一小段内核提供的代码和数据映射进每个进程(叫 vDSO),clock_gettime、gettimeofday 通常直接在用户态读出结果。 这就像前端把不常变的数据放在本地缓存,不必每次都请求后端。

程序
内核
硬件
程序
内核
硬件(终端)
clock_gettime:用户态直接读
事件日志(7)
当前状态发生了什么
用户态程序想打印文字,但无权直接操作硬件
用户态程序发起 write 系统调用
用户态 → 内核态CPU 切换模式,内核接手
内核态检查参数,通过后驱动硬件完成输出
内核态请求不合法,返回错误码
内核态 → 用户态带着结果返回,程序继续执行
用户态不陷入内核也拿到时间