文章目录
- 第一章 计算机系统概述
- 系统调用
- (一)什么是系统调用,有何作用
- (二)系统调用与库函数的区别
- (三)小例子:为什么系统调用是必须的
- (四)什么功能要用到系统调用
- (五)系统调用的过程
- 小结
第一章 计算机系统概述
系统调用
- 什么是系统调用?
- 系统调用与库函数的区别
- 小例子:为什么系统调用是必须的?
- 什么功能要用系统调用实现?
- 系统调用的过程
(一)什么是系统调用,有何作用
操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。其中,程序接口由一组系统调用组成。
“系统调用”是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务。
(二)系统调用与库函数的区别
系统调用和库函数的调用有区别。平时我们写程序时,可以用汇编语言的方式来直接请求系统调用服务。但是现在的编程更多的是使用高级语言编程,我们会直接使用高级语言的库函数,但是这些高级语言的库函数,在底层也会用到操作系统提供的系统调用功能,来请求操作系统的服务。
系统调用,应该是比高级语言的库函数更为底层的接口。
普通应用程序 | 可直接进行系统调用,也可使用库函数。有的库函数涉及系统调用,有的不涉及 |
---|---|
编程语言 | 向上提供库函数。有时会将系统调用封装成库函数,以隐藏系统调用的一些细节,使程序员编程更加方便。 |
操作系统 | 向上提供系统调用,使得上层程序能请求内核的服务。 |
裸机 |
不涉及系统调用的库函数:如“取绝对值”的函数
涉及系统调用的库函数:如“创建一个新文件”的函数
(三)小例子:为什么系统调用是必须的
生活场景:你去学校的打印店打印论文,你按下了WPS的“打印”选项,打印机开始工作。
你的论文打印到一半时,另一位同学按下了Word的“打印”按钮,开始打印他自己的论文。
思考:如果两个进程可以随意地、并发地共享打印机资源,会发生什么情况?
两个进程并发运行,打印机设备交替地收到WPS和Word两个进程发来的打印请求,结果两篇论文的内容混杂在一起了。这显然不是我们想要的结果。
由于系统当中有各种各样的并发的进程,而这些并发的进程又需要共享地使用类似于打印机设备这样的共享资源,但是这样的共享资源其实是需要各个进程互斥地共享的。
那么怎么实现对共享资源的互斥访问呢?最好的方式就是让操作系统内核来对共享资源进行统一的管理。上层的那些应用程序只能通过“系统调用”的方式,来请求操作系统,给它分配这种资源,之后,这个进程才可以对这种资源进行使用和访问。而各个进程的请求会由操作系统内核来协调处理,保证它们并发运行的时候不会发生这种混乱的事情。
解决方法:由操作系统内核对共享资源进行统一的管理,并向上提供“系统调用”,用户进程想要使用打印机这种共享资源,只能通过系统调用向操作系统内核发出请求。内核会对各个请求进行协调处理。
因此,系统调用是必须的。
(四)什么功能要用到系统调用
王道资料按照功能划分,分为了以下五种:
系统调用(按功能分类)
设备管理
完成设备的 请求/释放/启动 等功能
文件管理
完成文件的 读/写/创建/删除 等功能
进程控制
完成进程的 创建/撤销/阻塞/唤醒 等功能
进程通信
完成进程之间的 消息传递/信号传递 等功能
内存管理
完成内存的 分配/回收 等功能
拓展:可以搜索“Linux系统调用”,了解Linux操作系统提供了哪些系统调用。
总之,只要是对共享资源的访问,那肯定是需要系统调用来进行,因为这些共享资源是有限的(如:内存、I/O设备、文件),所以操作系统会对这些共享资源进行统一的管理和分配,因此应用程序在使用这些资源的时候就必须通过系统调用的方式请求操作系统内核来帮它进行接下来的处理。
应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管。因此凡是与共享资源有关的操作(如存储分配、I/O操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。
(五)系统调用的过程
一个应用程序运行在用户态,这个程序的各个指令会依次地被CPU执行。
当它想要发出系统调用的时候,它需要用传参数的指令,给CPU的寄存器当中传递一些必要的参数。比如在某寄存器当中传入了参数1
,参数1
的作用是:指明本次将要发出的系统调用是什么类型(如Linux系统中的“fork”,我指明一会儿要做的就是它)。而传递参数的指令可能会有多条(如图,还有参数2
),主要要看这次系统调用需要传递几个参数。而操作系统会根据应用程序提供的这些参数,来判断它想要的到底是哪种类型的服务。
当这些参数都放到了寄存器当中之后,应用程序就会执行一条特殊的指令,叫作陷入指令。这个陷入指令的执行,会引发一个内中断。CPU在检测到这个内部中断信号之后,它发现这个内部中断信号是由trap指令引起的,于是,CPU接下来就会暂停运行这个应用程序,转而去执行陷入指令处理程序
,即系统调用入口程序(可以理解为一种中断程序,只是由陷入程序引发的内中断)。【CPU转为内核态了】
接下来,系统调用程序会检查寄存器中的若干参数,最终知道这个程序想要调用的是哪种系统调用服务,于是,接下来,系统调用入口程序,就会调用特定的系统调用类型所对应的处理程序,然后让这个程序上CPU运行。
系统调用处理完毕后,CPU又会转为用户态,接着执行之前的应用程序。
传递系统调用参数→执行陷入指令(用户态)→执行相应内核程序处理系统调用(核心态)→返回应用程序
注意:
1、陷入指令是在用户态执行的,执行陷入指令之后立即引发一个内中断,使CPU进入核心态
2、发出系统调用请求是在用户态,而对系统调用的相应处理在核心态下进行。