02.操作系统概述.md

為{幸葍}努か 提交于 2020-02-28 21:12:58

2. 操作系统原理介绍

这篇文章主要想从基础介绍一下操作系统是如何运行的,主要专注于操作系统是如何对应用程序进行调度的。需要有前一篇文章作为基础

2.1 操作系统的目标和功能

2.1.1 作为用户/计算机接口的操作系统

  一个应用程序可以使用一种语言开发,如果没有操作系统的话,每一个开发者都需要十分了解计算机的硬件指令才行,这是不可想象的。操作系统做了一层抽象,就像开发应用程序的时候会写的各种工具类一样,操作系统对这些部分的操作提供了封装的模块,应用程序只需要调用就好了。
  同时还有一些通用的工作,比如创建程序,管理文件,控制io设备等,操作系统对这些操作都做了封装来简化编程。
下面是操作系统面向开发者或者用户的一些功能

  1. 程序开发:指一些辅助的应用程序开发工具
  2. 程序运行:运行一个程序需要很多不住,必须吧程序加载到内存当中,初始化io设备和文件,准备一些其他资源,操作系统为用户处理这些调度问题
  3. io设备访问:每个io设备都有自身的指令集或者控制信号,操作系统屏蔽了这些差异,程序员可以使用简单的读写操作来对这些设备进行访问
  4. 文件访问控制:对文件的访问不仅需要了解对应的磁盘存储设备的特性,还要了解文件的数据结构,同时有时候还要进行访问权限的控制,这些都由操作系统来完成
  5. 系统访问:操作系统控制对整个系统的访问(内存,io等)
  6. 错误检测和响应:存储错误,算术溢出等故障都是由可能出现的,操作系统需要对这些错误能够响应这些异常并记录或者报告
  7. 记账:记录各个资源的使用率数据

2.1.2 作为资源管理器的操作系统

一台计算机就是一组资源,这些资源用于移动,存储和处理数据,并对这些功能进行控制,操作系统负责管理这些资源。

2.2 操作系统发展简史

  计算机的发展经历了无操作系统(串行处理),简单批处理系统,多道批处理系统,分时系统通过对这些原理的学习,更加明白了计算机是如何运行的。解开了进程,线程等等后面的迷雾。
可以参考这里 进一步了解

2.2.1 串行处理

  这个时候是没有操作系统,程序员需要直接与计算机硬件打交道。这些机器在一个控制台上运行,包括 显示器,指示灯,触发器,某种输入设备和打印机。
  用机器代码编写的程序通过某种输入设备(如卡片阅读机)载入计算机。一个错误使得程序停止的时候,某个指示灯亮。如果程序正常完成,输出结果将出现再打印机中。
  这种系统的劣势不言而喻,在程序运行前的准备工作量非常大。如果用户申请了 1 个小时,但他的任务只用 35 分钟就运行完了,那多出来的 25 分钟就这么被浪费掉了。

2.2.2 简单批处理系统

  为了提高利用率,人们有了开发批处理系统的想法。批处理系统的中心思想就是用一个称为监控程序(monitor)的软件。刚刚提到了,串行处理需要用户自己去访问机器,时间段是固定的,但现在他们只需要把作业提交给计算机操作员,操作员会把这些作业按顺序组织成一批,然后把整个批作业放在输入设备上,供监控程序使用。
监控程序已经有点操作系统的意思了,它的的工作过程可以从下面两个角度理解:

2.2.2.1 从监控程序的角度来看

  一开始,监控程序掌握了计算机的控制权,为了做到这一点,大部分监控程序总是常驻内存,这部分称为常驻监控程序(resident monitor)。
  其他的部分,包括一些实用程序和公共函数,他们作为用户程序的子程序,在需要他们的作业开始的时候才会被载入。
  监控程序会从输入设备中读取一个作业,经过读入以后,作业就被放置在了用户程序区域,并且把控制权交给这个作业。当作业完成后,他将控制权再次返回给监控程序。监控程序立即读取下一个作业。每个作业的结果被发送到输出设备,交付给用户。

2.2.2.2 从处理器的角度来看

  一开始,处理器处理从内存中拿到的监控程序的指令,并执行,这些指令读入下一个作业的并存储到内存中的其他部分,读入作业后,处理器会遇到监控程序的一个分支指令,也就是跳转指令,分支指令指导处理器在用户程序的开始处继续执行。于是处理器就开始执行用户程序的指令了。直到遇到结束指令或者错误条件,这回导致处理器从监控程序所在位置取出指令执行。因此控制权交给作业,仅仅意味着处理器执行的指令都是从用户程序中的指令,而控制权返回给监控程序,意味着处理器执行的是监控程序的指令。对于处理器来说,这没有什么分别。

  有了监控程序后,计算机的利用率提升了:一道作业完成后立马就会开始下一道作业,没有任何空闲时间,也很少出现作业没完成就被终止的情况(基本上解决了串行处理的问题)。

2.2.2.3 硬件层面需要进行的支持

从上面可以看出来,监控程序就是一段普通的程序,完成固定的功能而已。
同时,为了使这个系统工作的更加可靠,对计算机的硬件也提出了一些要求,硬件要提供一下相关的功能:

  1. 内存保护:这一点很好理解,监控程序的内存空间不能被用户程序随意更改——不管是有意还是无意。一旦硬件检测到有用户程序试图使坏,就会将控制权直接转移给监控程序,监控程序会取消这个作业。
  2. 定时器:这项功能是为了防止一个作业独占系统,作业接管控制权后定时器自动打开。如果定时器时间到了而作业未运行完,就会停止用户程序,将控制权返回给监控程序。
  3. 特权指令:有的机器指令会被设置成特权指令(比如 I/O 指令),只能由监控程序执行。用户程序是不能直接使用这些指令的。当然用户程序可以请求监控程序为自己执行这个操作。特权指令就是为了限制用户程序的「权力」而设置的,毕竟老板和员工不可能有一样的话语权。
  4. 中断:早期的计算机模型中并没有中断的能力,添加这个能力使得操作系统从用户程序或者控制权的时候更加灵活

2.2.2.4 运行模式的概念

内存保护和特权指令引申出了程序的运行模式的概念。
用户程序以用户模式执行,此时有些内存区域是受保护的,特权指令也是无法执行的。
监控程序以内核模式执行,此时不仅可以执行特权指令,而且可以访问受保护的内存区域。

2.2.3 多道批处理系统

  cpu利用率低的主要原因就是 CPU 需要等待 I/O 操作,那我们让 CPU 忙起来不就可以了。多道批处理系统就是让 CPU 忙起来的秘诀。方法听起来很简单——在内存里多放几道用户程序,一旦有一个作业需要等待 I/O ,就立刻切换另一个可能不需要等待 I/O 的作业。这种处理,称为多道程序设计(multiprogramming)或多任务处理(multitasking)。

2.2.3.1 多道批处理系统的硬件支持

像简单批处理系统一样,多道程序批处理系统必须依赖于某些计算机硬件功能。
其中最显著的功能就是支持 I/O 中断(Interrupt)和直接存储器访问(Direct Memory Access,DMA)。(DMA 也需要中断的支持)
通过中断驱动的I/O或者DMA,处理器可以为一个作业发出I/O命令,设备控制器执行IO操作的时候,cpu执行另一个作业;IO操作完成后,处理器被中断,控制权传递给操作系统的中断处理程序,然后操作系统再把控制权个林各一个作业(不一定是原来io请求的那个作业,这个看具体的调度方案了)

2.2.3.2 多道批处理系统需要注意的新问题

  1. 作业调度:内存的空间是有限的,意味着一次性载入到内存的程序数量也是有限的,那么怎样从备选作业里选择合适的作业加载进内存就是一个问题,这就是就是作业管理。
  2. 内存管理:选择了作业,就需要为作业分配空间,那从空闲区的哪一部分为作业划空间就是内存管理需要解决的事情。

2.2.4 分时系统

  多道批处理系统可以说是现代操作系统的雏形了,它处理批作业时对处理器的利用率也比较令人满意,但面对多个交互作业,多道批处理系统就显得力不从心了。
  交互作业的出现很好理解,毕竟我们现在几乎所有应用程序都是交互式的,你滑动屏幕,这篇文章就会上下滑动,点一个分享,就会出现各种选项,等等等等。
  在交互作业中,难免需要等待用户做出操作,但又不可能让处理器停下来等你一个人,毕竟很多人都在用同一台计算机,因此分时系统应运而生。
  顾名思义,分时系统就是 n 个用户作业,操作系统控制每个用户程序以很短的时间为单位交替执行。因为人的反应相对机器要慢很多,所以如果控制得当,你会感觉自己是独占了这一台计算机一样。

  第一个分时操作系统是由麻省理工学院(MIT)开发的兼容分时系统CTSS,该系统运行在一台内存为32000个36位字的机器上,常驻程序占用了5000字,当控制权分配给一个交互用户的时候,该用户的程序和数据被载入到内容剩余的27000个字的空间中。程序通常在第5000个字的位置开始载入,这简化了监控程序和内存管理。系统时钟以0.2s一个的速度产生中断,在每个时钟中断出,操作系统恢复控制权,被将处理器分配给另一个用户。在固定的时间间隔内,当前用户被抢在,两一个用户被载入,这项技术称为时间片技术,为了便于以后恢复,他会保留老用户的程序状态,在新的程序载入前,老的用户程序会被写入到磁盘当中。当他再次被执行的时候会先从磁盘恢复这些数据和程序。

  看到这里,算是真正明白了操作系统的奥义,原来进程线程都算是概念的抽象罢了。实际上都是依赖中断来产生的,监控程序再修改PC,啊,感觉真是爽。
之前理解的操作系统就是一个单独运行的应用程序,他管理这计算机资源的方方面面,cpu调度,进程管理,内存分配等等。
  看到这里才明白,操作系统实际上就是一组普通的程序和其他程序一样,只是实现的功能不同而已。之前总是被进程等等概念所迷惑,这次看了这本书以后才真正解惑了。不妨从cpu的角度去理解程序运行。对于cpu来说,是无差别的,我只是根据PC(程序计数器)中的地址去取指令,然后执行,并没有什么进程,线程等东西。
  所谓进程,线程的切换,实际上就是cpu的PC中的值被替换到内存中不同的应用程序指令存放的地址而已。对于cpu来说,只有一个线程,就是不断的取指令然后执行。
  那么这个时候关键就是如何实现在不同的时候将PC中的值替换为不同应用程序所在的地址。一种常用的手段是使用使用定时器中断,因为中断一旦发生,cpu响应中断的时候就会执行中断的入口程序,实际上就是操作系统程序(也称为内核程序),这个时候内核就可以修改PC中的值,也就完成了应用程序的切换,实际上也就完成了所谓线程进程的切换。还有就是系统调用,比如阻塞式I/O请求,程序也会转到监控程序进行执行,这样的话监控程序就有机会将时间片分给别的程序了。

I/O调用的过程

  对应上面的1.9,我觉得可以这样去描述I/O的过程,当一个线程a发起了IO调用,应为IO属于特权指令,所以需要进行系统调用,这个时候程序进入了内核态,cpu的使用权交给了监控程序(操作系统),操作系统会发起一个IO指令,然后修改当前线程的一些状态,记录他在进行io等待,之后就将cpu使用权过度到其他线程了。在该线程的IO操作完成时,会有一个中断产生,cpu处理这个中断,然后把该进程的状态置为可调度状态。后面就可以进行cpu的统调度了。该线程就有机会获得cpu执行的时间片了。这样的调度方式,对应于当前的编程模式就是阻塞式IO,在IO响应之前,该线程对应的程序将不会获得调度。

  后来支持的nio应该就是非阻塞式的了,在发生IO调用的时候,会检查是否为阻塞式调用,如果是非阻塞式调用,则内核不会将进程的上下文切换,当前进程在调用完成后接着运行。同时注册一个回调函数,在中断回调的时候执行回调函数即可。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!