操作系统的服务端口:系统调用
前面在讲解高并发编程的时候我们讲解到了,用户态,内核态,用户空间与内核空间,我们说操作系统自身它在运行起来也是一系列的程序,它启动之后也有很多内核进程在后台工作,这些进程是工作在内核空间的,是操作系统正常运行并提供服务的必要进程,因为操作系统的权限最大,他负责管理着运行起来的各种用户进程的执行,当然也包括操作系统自身需要调度管理的应用,比如内存管理,进程之间的调度等等。
cpu提供了两种运行模式,内核模式与用户模式,也可以称为内核空间与用户空间。
在内核模式下,表示具备了最高权限,操作系统自身进程都是工作在内核模式下;
在用户模式下,进程执行的程序将受到一些限制,用户进程都是工作在用户模式下,该模式下的进程不能执行一些关键性的操作,比如打开文件,读取文件,或者写入文件等等吧。那可能有的同学又问了,我们前面写的程序不就是用户进程吗,不照样可以操作文件吗?我们继续来看。
用户进程工作在用户态,它是受限的,很多涉及到硬件的操作都无法执行,但是它们又需要操作它,就像前面我们的程序去操作文件一样,在这种情况下就只能请求工作在内核态的操作系统帮助完成这些操作,并将操作结果交给用户进程。
系统调用(system call)就是操作系统提供给用户空间进程,也就是我们普通的进程,像我们前面通过go评论所编写的程序去打开一个文件,读取写入文件那些操作,这些操作在底层实际上是请求操作系统提供的某些具有特殊权限的接口来完成的。
我们就举前面我们os.File相关操作的程序来看,以一张图:
读取之前必须先打开文件,但是用户进程是没有权限打开文件的,所以用户进程只能发送一个open()的系统调用请求操作系统去帮忙打开这个文件,操作系统打开这个文件后会将打开的结果——文件描述符交给用户进程,用户进程通过这个文件描述符就能去操作这个文件。再进一步,用户进程想要从这个打开的文件中读取一行数据,用户进程是没有权限读取文件的,只能发送一个read()系统调用请求操作系统去读取这一行数据,操作系统读取这行数据后就能交给用户进程。
我们可以看出,这里所调用的go语言提供的Open(),read()方法,其实在是系统底层,是由go语言运行时去调用系统内核所提供的open()和read()这种特殊权限的接口来完成的。我们可以这样理解,我们所调用的go语言相关的打开文件或者读取文件的函数,都是对系统底层接口的封装,这些由系统内核开放出来的接口,基本上任何编程语言都有提供对系统特殊权限接口的封装,为了方便我们各位同学理解,我们简单点就把它理解函数,好吧。
像这种涉及到了操作系统与硬件交互的操作必须有操作系统内核来完成,因为我们普通用户进程要想操作硬件设备,必须交操作交给内核,由内核向计算机发出指令动作,一般是由汇编语言编写可以与硬件交互,当然这些不是我们本次课程讨论的内容。