过程调用
- 定义:在一个程序的内部,在一个权限的多个模块之间发生的函数调用
发生地点在用户空间内部,使用普通的栈来完成参数的传递、保存返回地址和局部变量。调用者和被调用者都拥有相同的级别权限(用户态)无法直接访问受保护的硬件资源。开销很小(参数压栈,出栈,跳转操作等)。
例子:你自己在携程写程序的时候,调用了一个自己写的sum()函数,或者使用c标准库中的printf函数(但是需要注意的是printf内部最终会调用系统调用write来真正的在屏幕上进行输出字符的操作,但是调用printf这个函数的动作本身是过程调用)。
系统调用
- 定义:运行在用户态的应用程序需要操作系统的内核为其提供运行的服务,例如请求io操作来和硬件进行交互,系统调用是提供给程序员的编程接口,是程序员编写的程序和操作系统内核交互的唯一方法和接口。
系统调用的过程发生在内核态。系统调用是一个严格和预先定义的接口,每个系统调用都有一个唯一的系统调用号,来表示一个唯一的服务,例如open和read,write系统调用等,调用的时候,其参数一般需要传入特定的寄存器,以便内核读取。
系统调用是用户空间程序与内核空间交互的桥梁。程序员在高级语言中调用系统调用函数(如打开文件、读写数据。但这些程序本身只是一个预先定义的函数,和普通函数无二,但是这些函数底层封装了对系统调用的调用,是系统调用的集合和封装,你可以认为是间接通过这些函数请求了操作系统的服务),但这些函数在底层会触发一个软中断。这个软中断使 CPU 从用户模式切换到内核模式(称为“陷入”),内核接管执行,完成请求的服务后返回用户模式。
当然程序员也不直接编写陷入指令,同样是通过高级语言封装好的函数间接调用。底层指令由编译器或操作系统处理。
tip: 这里的内核态,你可以理解为计算机cpu内有一个小开关,这个开关由硬件直接控制(为了保证其安全性),当这个开关置为“1”的时候,表示当前为内核态,反之(“0”)则为用户态,只能执行用户态的程序。

对比
| 特性 | 过程调用 | 系统调用 |
|---|---|---|
| 发生空间 | 用户空间内部 | 从用户空间切换到内核空间 |
| 权限级别 | 不切换(始终用户态) | 切换(用户态 -> 内核态 -> 用户态) |
| 实现机制 | 普通跳转/栈操作 | 软中断 / 陷阱 / syscall 指令 |
| 性能开销 | 小 | 比较大(需要上下文切换和安全检查) |
| 安全性 | 无需额外检查 | 内核会进行严格的参数和安全检查 |
| 依赖性 | 依赖于编译器/语言 | 依赖于操作系统内核 |
| 例子 | my_function(), sqrt() | open(), fork(), send() |
1793

被折叠的 条评论
为什么被折叠?



