首先我们先来复习一下操作系统的概念和作用
操作系统是用户和硬件之间的一层媒介程序,为上提供编程接口,为下调用资源,管理驱动,以使用硬件。
从以上的表述我们可以看出OS的两点作用,第一个是对下直接管理和使用硬件,第二个则是对上提供管理和使用硬件的接口。而在操作系统中,对下管理和使用硬件的那些程序,我们称之为内核程序,内核程序主要要做的一些事是
而使用内核程序提供的那些接口我们则可以称之为用户程序。例如我们的一些网卡或者其他的驱动,也是属于内核程序对上提供的接口,用户可以通过这些驱动来管理网卡。因此我们可以规范一下内核程序和用户程序的概念,以下为我的个人理解
内核程序:操作系统中,可以访问所有硬件设备,如网卡、内存设备等的一些特殊的高权限的系统程序,
用户程序:只能有限的访问部分内存空间,对硬件设备没有访问权限的低权限的应用程序或系统程序
有人可能会问了,那我平常用一些自己写的应用程序,也可以访问硬盘里的东西,或者开启对摄像头的控制,这是不是说明我也能访问硬件设备呢?当然不是啦!我们平常写的程序,最后实际上可以看作,运行到了一定的阶段,就会托管给内核程序,由内核程序去完成的。
并且在操作系统中,内存空间也被划分成了内核空间和用户空间。内核程序会始终的占据着内存的一些空间,方便处理器去调用内核程序,而用户程序是自始至终接触不到这些内核空间的。
我们运行一个程序的整个流程是这样的,用户程序完成一定的事情,然后交由内核程序去处理,内核程序处理完毕之后,将处理的结果或者说处理完成的数据,再交由用户程序去执行,在整个过程中,用户程序是完全接触不到内核空间的。
那么问题来了,操作系统为什么要这么大费周章的划分内核和用户之间的区别呢?我们从实际生活的一个例子出发去探讨这个问题。假设你去一家饭店吃饭,点好菜,由服务员通过餐口,转告给厨房的工作人员,等厨房的工作人员,比如厨师,切菜的人员,把菜做好了,再通过送餐口让服务员送到你的面前。
我们来分析一下这个过程,在这个过程中,你点菜这个操作,就相当于操作系统中的用户程序,而服务员和送餐口,就是厨房和外部连接的通道,服务员和送餐口都可以看作是操作系统中的驱动程序,你通过他们来告诉厨房你需要什么菜。然后厨房做菜的这个过程,就是相当于内核处理用户程序的请求,最后从送餐口送餐的这个过程,就等于是内核处理完之后,将处理完成的数据再转交给用户程序。而做菜的过程,对于顾客来说是完全的一个黑盒,用户不知道里面发生了什么,也无法参与做菜,用户能看到的,只有从餐口端出来的那盘菜。另外像厨房,仓库这些重要的地方,你作为一个顾客肯定是进不去的,这些地方只有饭店的核心人员,比如厨师,老板才能进入,你能活动的区域只能饭店的大厅这些公共的区域。这就相当于操作系统把内存的空间,划分为了用户空间和内存空间,并且强制规定用户不允许进入内存空间。
因此我们大致上可以得出几个概念对应例子中的等式,
内核程序 == 厨师 切菜人员,备菜人员,每种程序有不同的功能,同样的每类职业也有不同的职责,
用户程序 == 顾客 每个顾客想要的菜都不一样,对内核的请求也不一样
内核空间 == 厨房 厨房只允许厨师和备菜的进入,同样的内核空间也只允许内核程序进入
用户空间 == 大厅
到了这里,我们就可以来回答一下上面的问题了 “操作系统为什么要这么大费周章的划分内核和用户之间的区别呢” ,答案是首先操作系统的核心是内核,可以访问几乎底层的所有设备和空间,至关重要,为了保护内核的安全,因此操作系统会强制性的用户程序不允许访问内核空间,内核空间只有内核程序可以访问,用户程序只允许通过内核提供的接口来请求,这样划分对整个操作系统的稳定性和安全性是一种有力的保护。其实这样也很好理解,试想如果是一家饭店的厨房,不管是谁都可以随随便便的进出,毫无限制,那这家厨房的食品安全问题一定也得不到保障,你还会放心的去这家饭店吃饭吗?
我们通过上面举的例子,再来总结操作系统处理数据的整个过程就会显得好理解很多了。当我们需要读取一条数据的时候,首先需要发请求告诉内核,我需要什么数据,等内核准备好数据之后 , 再从内核空间拷贝到用户空间 注意加粗的部分,这两个阶段至关重要
第一阶段 :等待内核准备数据
第二阶段:数据从内核空间拷贝到用户空间
那么为什么我们明明是讲网络IO,却要大费周章的讲这么多操作系统的东西呢,因为本身IO操作就是由操作系统控制的,而我们发送一个IO请求,IO读写也是要经过以上的这些内核程序执行数据准备和拷贝过程的,如果不把这些讲明白了,那么后面我们要提到的,阻塞和读写过程必然将是一团雾水。而以上我们所重点强调的两个阶段,则是决定着各种IO模型的条件。包括后面要讲到的阻塞IO(BIO),非阻塞IO(NIO),IO多路复用,信号驱动IO,全异步IO(AIO),都是和上面两个阶段以及操作系统知识密切相关的。以上的两个过程和操作系统整个数据处理流程,务必要理解和记住,之后的文章,都是基于以上OS的整体流程,可以说是网络IO的基石中的基石
操作系统为了安全性和稳定性考虑,因此将执行程序分为内核程序和用户程序,将内存空间分为内核空间和用户空间,内核程序对下直接对硬件进行使用和管理,对上提供接口给用户程序使用
用户程序不允许直接访问内核空间,而是转交给内核程序,由内核程序处理好,再拷贝到用户空间供用户程序使用
不管是对于IO还是其他数据处理的操作而言,有两个重点阶段,分别是,一、等待内核准备数据阶段,二、数据从内核空间拷贝至用户空间阶段,这两个阶段决定了IO的阻塞于否,非常重要