1. 概念: 操作系统对上提供服务的接口
2. 程序调用与系统调用的不同之处?
3. 开销?
一、标准C库的例子
-
应用程序调用printf()时,会触发系统调用write()(实现在内核)。
二、系统调用
-
操作系统服务的编程接口
-
通常由高级语言编写(C或者C++)
-
程序访问通常是通过高层次的API接口而不是直接进行系统调用
-
三种最常用的应用程序编程接口(API)
-
Win32 API 用于WIndows
-
POSIX API 用于POSIX-based systems(包括UNIX,LINUX,Mac OS X)
-
Java API 用于java虚拟机(JVM)
-
三、系统调用的实现
-
每个系统调用对应一个系统调用号
-
系统调用接口根据 系统调用号 来维护表的索引
-
-
系统调用 接口 调用内核态中的系统调用功能实现,并返回系统调用的状态和结果
-
用户不需要知道系统调用的实现
-
需要设置 调用参数 和 获取返回结果
-
操作系统接口的细节大部分都隐藏在应用编程接口后
-
通过运行程序支持的库来管理
-
-
-
系统调用
-
INT 和 IRET 指令 用于系统调用
-
系统调用时,堆栈切换 和 特权级 的 转换
-
为了保护内核的实现,这里内核和用户态的应用程序之间使用不同堆栈,所以这里用一个堆栈切换,切换之后由于处于内核态,可以使用特权指令,可以直接对设备进行控制。
-
-
-
函数调用
为了调用一个函数需要把参数压到堆栈里,转到相应的函数去执行,执行时从堆栈里获取我的参数信息执行,执行返回的结果放在那里,再返回回来。上面函数调用里知道我相关的返回结果,然后用这个结果继续向下执行。
-
CALL 和 RET 用于常规调用
-
常规调用 时没有 堆栈切换
-
-
四、中断、异常和系统调用的开销
系统调用比函数调用更安全,但是开销大(由于有一个用户态到内核态的切换)
-
超过函数调用
-
开销
-
引导机制
-
建立内核堆栈
-
验证参数
-
内核态映射到用户态的地址空间
内核需要访问到用户态的一些信息,这些映射会导致缓存会有变化
-
更新页面映射权限
-
-
内核态独立地址空间
-
TLB(其中内容会失效)
-
【1】源自《学堂在线》-清华大学 向勇, 操作系统