操作系统是将我们的硬件CPU、内存和各种外部的IO设备进行抽象和调用给上层应用程序的操作平台。


如果没有操作系统,某一个应用程序要想在这个主机或着说硬件上运行,那么他需要自己去管理CPU调用、内存的使用以及IO设备的使用,从哪儿都数据?数据输出的时候写到哪儿去?都需要进程自己进行管理。这太麻烦不是吗?任何一个人自己开发一个应用程序,都这这么写,而且也不方便让多个应用同时进行工作,为什么呢?因为大家看见的CPU和内存都是全部的,在相互运行的时候一定会造成资源争用,一定会相互打架。所以基于这样需求,就出现了这样的一个东西,资源管理层,他什么也不干,主要工作就是将我们的硬件资源进行一次抽象。这么抽象呢?把所有硬件资源的使用都虚拟成了系统调用,术语叫做System Call。


所以有了这个东西之后呢,我们的应用程序需要用到的内存以及但凡需要跟硬件打交道,都需要进过操作系统的System Call。比如说我需要调用CPU,应用程序会向操作系统发起系统调用,在操作系统当中,有一个系统调用是向CPU进行抽象调用的,操作系统会使用该调用将CPU的资源分配给该应用程序使用。所以我们的应用程序只要要用到硬件资源,它只需要向操作系统的内核发起系统调用即可,这就是为什么我们在进行系统性能调优和监控的时候,会发现我们系统的某一进程会不断的向操作系统发起系统调用。这大大的方便了应用程序。


随着操作系统的发展,操作系统又将多个不同的系统调用按照某种机制分配到不同的进程上去,从而使得我们的应用程序具备多种的功能。操作系统在这里其实也是类似于一种进程监控器的存在,是一个特殊组件。我们可以称之为Process Monitor。它能够监控着每一个进程的运行。进程运行在操作系统之上,他看到的仅仅是操作系统,或着是操作系统分配给他的CPU时间片,内存存储空间以及IO设备,他能够或得某一个IO设备的使用权的时候,就意味着他占用了这个IO的总线,我们姑且可以这样理解。我们的IO设备真正的要跟CPU通讯,跟应用程序通信,那就意味着IO设备会使用总线跟CPU或着内存进行通信。


由此,操作系统负责其上运行的应用程序的每一个对硬件资源的申请,所以使得第一个进程在使用CPU的时候,第二个进程就只能等待,假设我们的电脑就一颗CPU。但是好在我们的CPU速度非常快,而进程本身所需要的CPU时间有非常短,因此对于很多用户看来,我们的多个应用程序是并行进行的。事实上如果只有一颗CPU的情况下并不是并行的而且也无法并行。同时,每一个进程在运行的时候都需要一段内存空间,而且这段内存是连续且平滑的。从低端内存地址到高端内存地址,高端地址是栈,低端地址的代码段、数据段,BSS段等等。但是我们的内存总是有限的,不可能没一个应用程序都给它所需要的那么多的内存空间,因为一个应用程序虽然说需要那么多的地址,但是在实际运行的时候。其实是用不到那么多是空间地址的。很可能只需要一点就足够了。由此,操作系统提供了一种管理机制,或者说结合CPU完成了一种管理机制。将每一个进程所使用的线性地址空间转换成物理地址空间,这种映射是按照页面的方式进行映射的,其实进程所使用的地址,分为rss常驻内存级、Page Cache,以及anon Page匿名页,页缓存等等,那么什么是rss常驻内存级呢?就是我们的进程启动的时候这段地址必须是位于物理内存空间的地址。是绝对不可以被交换出去的。那么什么是页缓存呢?页缓存就是我们打开的文件,这些文件通常都保存在我们的Page Cache中,Page Cache可以交换到交换分区当中,也可以被清除出去,因为他就是缓存,没有的时候我们再打开一次文件不就完了嘛。上面匿名页?匿名页就是我们的进程在运行过程中所产生的一些中间数据,比如我们堆中的数据,通常都是匿名页或着说有一部分是匿名页。所以,当第一个进行打开了文件,占据了很大的内存空间,第二个进程需要在使用内存的时候内存空间不够了,那怎么办呢?把第一个文件打开的文件都统统的清除出去,就腾出空间给第二个进程打开文件所需要的空间了。这时如果第一个进程发现打开的文件没了咋办?这个时候就会产生一个东西,名叫缺页中断。而后,系统会从新将第一个进程所打开的文件从新调用回来。要想完成线性地址都物理地址的转换,需要使用到一个技术,名叫MMU。但是MMU没一次转换都需要实现一级页面的查找,二级页面的查找,然后在实现平移,在实现中断,才能够得到内存空间。这是非常麻烦的。为了加速这个过程,于是有了一个技术,叫TLB。


还有,IO设备是怎么实现和CPU交互的,CPU怎么知道他那一次是和哪一个IO设备打交道的呢?当前系统中我们可能存在很多的IO设备,但是我们的总线是不是只有一个,处理机制也只有一个。IO设备在启动的时候必须要向整个系统注册他自己的IO端口,在操作系统当中,IO设备的端口也是连续的,一个IO设备可以使用一片连续的IO设备端口。端口一般也是从0-65535这个范围内。那么如果某一个端口被其实IO设备注册使用了,那么别的IO设备在注册的时候就只能使用剩余的其他端口了。但是一般来讲我们的端口是用不完的。同时,为了让CPU知道在哪一个时刻IO设备产生了那些事件,每个IO设备还需要向CPU注册中断,必须要注册使用中断号。所以CPU只需要知道那个IO端口注册使用的是哪一个IO设备,就么就能实现IO设备和CPU之间的准确交互。而中断是IO设备和CPU之间建立的紧急沟通平台。就好比说中美关系,在正常情况下都是通过管理外部事务的部门进行官方之间的信息沟通,但是在情况比较紧急的情况下,领导人与领导人之间需要有专线进行紧急事件的沟通,以避免紧急事件照成误判而发生战争或者其他影响。有了中断,一旦某个IO设备向CPU来了一个IO中断信息,比如说网卡,有人ping过来了一个报文,大家知道这个报文在计算机的底层其实表现的就是一电信号,报文不立即处理的话就会立即消失的。这个报文保存在内存的网络缓存区中。如果是磁盘IO发送过来的中断信息呢?要把他读进来放在磁盘缓存区当中,所以操作系统中,每个设备都会有缓存区的。一般来讲,一旦某个IO设备产生中断了,意味着这个事件比当前运行的进程更紧急,所以操作系统对于中断的处理应该是很优先的。那么我们的系统在上面时候才会产生中断呢?允许中断呢?在任何一个时钟中断到来之前,能够实现对CPU的抢占。因此当我们的系统有一个设备接入进来的时候,该设备会向中断控制器发起一个中断请求,中断控制器产生请求之后,CPU马上就能够意识到有设备进来了,那么CPU是怎么意识到的呢?CPU里面有一种东西叫做针脚,这个针脚一旦有了电压,CPU马上就意识到了。CPU一旦产生中断,CPU就会告诉内核中断产生,这个时候内核必须要完成模式切换,而这个时候内核可能正在运行着一个进程,那这个进行就会被清除出去的。让内核处理该中断,将信息读进内存当中。


如果我们需要从磁盘上读取很多文件进来,我们的CPU必须要一个一个的指挥着,那这样的话,我们的CPU大量的时间都消耗在数据交换上了,为了避免这种情况,CPU可以在内存中开辟一段空间,来存储这段数据,而后CPU吧这个控制权交给这个设备的DMA,由DMA负载取数据。数据取完之后放到内存里面,DMA告诉CPU数据取完了。DMA是怎么告诉CPU呢?又是一次中断。综合来说就是一个外部的硬件需要和CPU打交道的时候,必须要通过中断来完成。CPU必须要知道没一次的中断都是什么,他的IO端口是什么。然后才能当前的这些动作和IO设备关联起来,并且在需要的时候将这个IO设备附加到进程上面。