操作系统 --王道计算机考研--学习笔记


前言

  • 这篇笔记不怎么适合用作考研,因为所学专业,我会对这门课比较深入地学习。

  • 因为本人也是初学,所以在里面转载了很多大佬的文章,转载片段会进行说明,有些是书籍片段,就没进行声明。如果侵权,联系我删除。

  • 本文章主要参考视频为:王道计算机考研的视频,参考书籍有:

  • 另外笔记中如果有错误,疑惑等可以在评论区留言,我们一起探讨

第一章 引言

计算机软件大致分为两类:系统软件和应用软件。

  • 系统软件管理计算机本身及应用程序;最基本的系统软件是操作系统(operating system),它控制计算机的所有资源并提供开发应用程序的基础。

系统软件包括
操作系统类(操作系统是控制和管理计算机各种资源、自动调度用户作业程序、处理各种中断的软件。操作系统的作用是控制和管理系统资源的使用,是用户与计算机的接口。目前比较流行的操作系统有DOS操作系统、UNIX操作系统、Windows操作系统(是单用户多任务图形界面操作系统)。)、
语言处理程序类(语言处理程序的任务就是将源程序翻译成目标程序)、
服务性程序类(服务程序(也称为工具软件)扩大了机器的功能,一般包括诊断程序、调试程序等。常用的微机服务软件程序有QAPLUS、PCTOOLS等)、
标准库程序类(为方便用户编制程序,通常将一些常用的程序段按照标准的格式预先编制好,组成一个标准程序库,存人计算机系统中,需要时,由用户选择合适的程序段嵌入自己的程序中。)、
数据库管理系统类(数据库管理系统有各种类型,目前许多计算机包括微型机都配有数据库管理系统,如FoxPro、Oracle、Sabase等)五类。

  • 应用软件执行用户最终所需要的功能,包括各种科学计算类程序,工程设计类程序,数据统计与处理程序。

计算机系统由硬件、系统程序和应用程序组成
       许多年以前人们就认识到必须找到某种方法将硬件的复杂性同程序员分离开来。经过不断探索和改进,目前采用的方法是在裸机上加载一层软件来管理整个系统,同时给用户提供一个更容易理解和进行程序设计的接口,这被称为虚拟机(virtual machine)。这样一层软件就是操作系统
在操作系统之上是其他系统软件,包括命令解释器(shell)、窗口系统、编译器、编辑器及类似的独立于应用的程序。要注意它们本身并不是操作系统的组成部分,尽管它们通常由计算机厂商提供。这一点很重要,操作系统专指在核心态(kernel mode),或称管态(supervisor mode)下运行的软件,它受硬件保护而免遭用户的篡改。编译器和编辑器运行在用户态(user mode)。如果用户不喜欢某一个编译器,他可以自己重写一个,但他却不可以写一个磁盘中断处理程序 ,因为这是操作系统的一部分,而且硬件阻止用户对它进行修改。
系统软件之上是应用软件,这些软件可以是购买的或者是用户自行开发的,它们用来解决特定的问题,如字处理、表格处理、工程计算或者电子游戏等。

1.1 什么是操作系统?

       很难给出操作系统的准确定义。操作系统是一种运行在内核态的软件——尽管这个说法并不总是符合事实。部分原因是操作系统有两个基本上独立的任务,即为应用程序员(实际上是应用程序)提供一个资源集的清晰抽象,并管理这些硬件资源,而不仅仅是一堆硬件。另外,还取决于从什么角度看待操作系统,读者多半听说过其中一个或另一个的功能。下面我们逐项进行讨论。

       没有任何程序员想要在硬件层面上和硬盘打交道,因此,所有的操作系统都提供使用硬盘的又一层抽象:文件。使用该抽象,程序能创建、读写文件,而不用处理硬件实际工作中那些恼人的细节。
       抽象是管理复杂性的一个关键。好的抽象可以把一个几乎不可能管理的任务划分为两个可管理的部分。其第一部分是有关抽象的定义和实现,第二部分是随时用这些抽象解决问题。
       几乎每个计算机用户都理解的一个抽象是文件,正如上文所提到的。文件是一种有效的信息片段,诸如数码照片、保存的电子邮件、歌曲或Web页面等。处理数码照片、电子邮件、歌曲以及Web页面等,要比处理SATA(或者其他)硬盘的细节容易,这些磁盘的具体细节与前面叙述过的软盘一样。
       操作系统的任务是创建好的抽象,并实现和管理它所创建的抽象对象。本书中,我们将研究许多关于抽象的内容,因为这是理解操作系统的关键。

请添加图片描述
从引言来看,我们可以知道操作系统是一种软件,它运行在硬件上,又为更高层的应用软件提供服务。

  • 为上层用户、应用程序提供简单易用的服务
  • 是一种系统软件
  • 负责管理协调硬件,软件等计算机资源的工作
    请添加图片描述

1 操作系统作为虚拟机

       对多数计算机而言,在机器语言一级的体系结构(指令集、存储组织、I/O和总线结构)上编程是很困难的,尤其是输入输出操作。最基本的命令是读数据和写数据。它们均需要13个参数,所有这13个参数被封装在9个字节中。这些参数指定的信息有:欲读取的磁盘块地址、每条磁道的扇区数、物理介质的数据记录格式、扇区间隙、以及对已删除数据地址标识的处理方法等。当磁盘操作结束时,控制器芯片返回23个状态及出错信息,它们被封装在7个字节中。此外,程序员还要注意步进电机的开关状态。如果电机关闭,则在读写数据前要先启动它(有一段较长的加速时间)。还要注意电机不能长时间处于开启状态,否则将损坏软盘,所以程序员必须在较长的启动延迟和可能对软盘造成损坏之间作出折衷。
       显然,程序员不想涉及硬件的这些具体细节(也包括硬盘,它与软盘不同,但同样很复杂)。他需要的是一种简单的高度抽象的设备。这种将硬件细节与程序员隔离开来、同时提供一个简洁的命名文件方式的程序,就是操作系统。与磁盘抽象类似,它还隐藏了其他许多低层硬件的特性,包括中断、时钟、存储器等。总之,操作系统提供的每一种抽象都较低层硬件本身更简单、更易用。

从这个角度看,操作系统的作用是为用户提供一台等价的扩展计算机,或称虚拟机,它比低层硬件更容易编程。

关于虚拟化技术可以看这篇文章会有更加深入的了解。
虚拟化技术的分类及介绍在这里插入图片描述

两类虚拟机管理程序(VMM)的对比
在这里插入图片描述

2 操作系统作为资源管理者

       按照自底向上的观点,操作系统则用来管理一个复杂系统的各个部分。现代计算机都包含处理器、存储器、时钟、磁盘、鼠标、网络接口、激光打印机以及其他许多设备,从这个角度看,操作系统的任务是在相互竞争的程序间有序地控制这些设备的分配。
       当一台计算机(或网络)有多个用户时,因为用户间可能相互影响,所以管理和保护存储器、I/O设备以及其他设备的需求随之增加。而且用户往往不仅需要共享硬件,还要共享信息(文件、数据库等)。总之,此时操作系统的首要任务是跟踪资源的使用状况、满足资源请求、提高资源利用率、以及协调各程序和用户对资源的使用冲突

资源管理包括用以下两种不同方式实现多路复用(共享)资源:在时间上复用在空间上复用

  • 时间复用当一种资源在时间上复用时,不同的程序或用户轮流使用它。至于资源是如何实现时间复用的则是操作系统的任务。例如打印机的共享,当多个打印作业在一台打印机上排队等待打印时,必须决定将轮到打印的是哪个作业。
  • 空间复用每个客户都得到资源的一部分,从而取代了客户排队。例如,通常在若干运行程序之间分割内存,这样每一个运行程序都可同时入驻内存(例如,为了轮流使用CPU),假设有足够的内存可以存放多个程序,那么在内存中同时存放若干个程序的效率,比把所有内存都分给一个程序的效率要高得多。当然,如此的做法会引起公平、保护等问题,这有赖于操作系统解决它们。有关空间复用的其他资源还有磁盘,在许多系统中,一个磁盘同时为许多用户保存文件。分配磁盘空间并记录谁正在使用哪个磁盘块,是操作系统的典型任务。

3 为上层提供服务-- 系统调用

       操作系统的主要功能是为管理硬件资源和为应用程序开发人员提供良好的环境来使应用程序具有更好的兼容性,为了达到这个目的,内核提供一系列具备预定功能的多内核函数,通过一组称为系统调用(system call)的接口呈现给用户。系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,将处理结果返回给应用程序。

【在3.3中有详细讲解】

       用户程序通过调用这些API获得操作系统的服务。例如,如果用户程序需要进行读磁盘操作,在C程序代码里将使用下面的语句:result=read(fd, buffer, nbytes);
       这个read函数是C语言提供的库函数,而这个库函数本身则是调用的操作系统的read系统调用。注意这里有两个read,一个是read库函数,由程序语言提供;另一个是read系统调用,由操作系统提供。编译器在看到上述语句后将read库函数扩展为read系统调用。在真正执行时,操作系统将完成上述文件的读操作。
系统调用按照功能可以划分为六大类:

  • 进程控制类
  • 文件管理类
  • 设备管理类
  • 内存管理类
  • 信息维护类
  • 通信类
    系统调用的过程

系统调用过程](https://img-blog.csdnimg.cn/14e29f95af334c1488089881b39a88ae.png
扩充:Linux系统调用

2.操作系统特征与发展分类

在这里插入图片描述

2.1 操作系统特征

1.并发

并发:指两个或多个时间在同一时间间隔内发生。这些事件宏观上是同时发生的,但微观上是交替发生的。
并行:指两个或多个事件在同一时刻同时发生。
操作系统的并发性指计算机系统中“同时”运行着多个程序,这些程序宏观上是同时运行着的,而微观上看是交替运行的。操作系统是伴随着“多道程序技术”而出现的。因此,操作系统和程序并发是一起诞生的
【注意】:单核CPU同一时刻只能执行一个程序,各个程序只能并发地执行;
多核CPU同一时刻可以同时执行多个程序,多个程序可以并行地执行。
对于4核CPU来说可以并行地执行4个程序。

2.共享

共享:即资源共享,是指系统中地资源可供内存中多个并发执行地进程共同使用。
在这里插入图片描述
       所谓的“同时”一般是宏观上的,而在微观上,这些进程可能交替地对该资源进行访问地(即分时共享);但有时候在微观上也确实在同时地共享这个资源,比如说在玩游戏地时候一边在听歌,那么你会发现你的扬声器这个声音输出设备,一边在播放音乐,一边在播放游戏音效,所以对于扬声器来说,是同时被使用的。
生活示例:
在这里插入图片描述
并发和共享的关系
并发和共享的关系

3.虚拟

虚拟是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体是实际存在的,而逻辑上对应物是用户感受的。比如:3A游戏有些地图没加载,只在内存加载你现在的地图。
虚拟技术
(第三章会详细讲解)
空分复用技术:
在这里插入图片描述

时分复用技术:
在这里插入图片描述

4.异步

异步是指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
举例:
在这里插入图片描述

2.2 操作系统发展和分类

操作系统发展和分类
手工操作阶段:
手工操作阶段
单道批处理系统:
在这里插入图片描述
多道批处理系统
在这里插入图片描述
分时操作系统
在这里插入图片描述
实时操作系统:
在这里插入图片描述
其它几种操作系统
在这里插入图片描述

3.操作系统的的运行机制和中断异常、系统调用

3.1 操作系统的运行机制

运行机制
预备知识:程序是如何运行的?
程序是如何运行
       编译器将C语言(高级语言)代码翻译成机器能看的懂的二进制代码,也就是机器指令,然后CPU一条条执行这些机器指令的过程就是程序运行的过程。

       我们普通程序员写的程序就是“应用程序”。微软、苹果有一帮人负责实现操作系统,他们写的是内核程序
。由很多内核程序组成了操作系统内核,或简称内核(Kernel)。内核是操作系统最重要最核心的部分,也是最接近硬件的部分。甚至可以说,一个操作系统只要有内核就够了(eg: Docker->仅需Linux内核)操作系统的功能未必都在内核中,如图形化用户界面GUI.

特权指令 和 非特权指令

这一段转载作者:无法获取该昵称 出处:bilibili
在这里插入图片描述

  • 特权指令:从指令系统(指令集)角度定义,在指令系统中拥有用于管理硬件和整个系统安全的指令,让程序随意使用具有极高危险性。不得在用户态(目态)执行,只能在核心态(管态)执行,用户态程序如果运行特权指令将发生异常,并切换到管态由操作系统接管cpu。所以用户程序不得使用特权指令,需要执行特权指令需要使用防管指令,进入核心态。 举例:启动I/O、内存清零、修改程序状态字、设置时钟 允许/禁止终端、停机等
  • 非特权指令:用户程序可以使用的指令。 举例:控制转移、算数运算、取数指令、访管指令(使用户程序从用户态陷入内核态)

• 访管指令
○ 同样从指令集的角度定义,或者说从硬件角度(cpu状态)。防管指令,是用户程序自愿进管的指令(进管同时也意味着程序放弃cpu的控制权),该指令本身属于非特权指令,可在用户态执行,执行后进入核心态。核心态是通过cpu置相应标志表明当前处于核心态。cpu进入核心态后可以执行指令集中的所有指令(包括特权指令和非特权指令,但不执行访管指令)。
• 陷入指令【关于陷入指令还可以看下这篇用户态的陷入指令(trap指令,访管指令)
○ 原则上可看作访管指令,但是从操作系统的角度定义的。访管强调的是cpu从用户态切换到了核心态,可以执行指令集中的所有指令。而陷入(自陷、陷阱)指令强调程序从用户程序切换到了操作系统,陷入指令即汇编中的中断指令,执行陷入指令程序中断,跳转到中断服务程序(操作系统的代码)。所有访管强调的是可以执行特权指令,陷入强调的是进程放弃cpu,交还给操作系统。其实核心态和操作系统是不可分割的:道理很显然,进入核心态(管态),必然需要“跳转”到操作系统,不然区分用户态和核心态就没有了意义,如果程序执行完访管指令后,只是进入了管态,之后仍然执行自身的代码,那用户程序将可以为所欲为,显然不能允许。另一方面,如果cpu跳转到了操作系统,没有进入管态,那操作系统也无法执行特权指令,管理整个机器,显然也不行(当然也存在操作系统一部分运行在用户态,一部分(即内核)运行在管态,此时操作系统获取cpu控制权后不一定是处于核心态)。所有管态就是运行操作系统,访管指令本质上就是一条陷入(中断)指令。

内核态 和 用户态

在这里插入图片描述

  • 内核态:运行操作系统程序,操作硬件
  • 用户态:运行用户程序

详细讲解请看这篇文章用户态与内核态 – 帮你解惑,直达本质

用户态、内核态的切换

在这里插入图片描述

3.2 中断 异常

中断异常
       所谓中断是指CPU对系统发生的某个事件做出的一种反应,CPU暂停正在执行的程序,保留现场后自动地转去执行相应的处理程序,处理完该事件后再返回断点继续执行被“打断”的程序。
       例如:任务A需要用到打印机,打印的时间相对于cpu来说会很长,如果在打印期间死等打印机太浪费资源,所以出现了中断,cpu会先放弃该任务的执行,然后转去执行其他任务,当打印机打印好后就会发出中断信号给cpu,cpu就暂停当前任务的执行,继续运行任务A。

这位博主讲的中断我觉得挺好的 操作系统中断

1.中断的作用

在这里插入图片描述
       一个应用程序在上CPU运行之后,就会一直运行下去,除非发生了中断,而一旦发生了中断,就会让CPU立即停止此时正在执行的应用程序,转移相应的内核程序。所以中断是让操作系统内核重新夺回CPU使用权的唯一途径。

2.中断的类型

在这里插入图片描述
在这里插入图片描述

王道视频是讲的是广义上的中断,我在这是以狭义的中断为角度将中断分为三类。

中断可分为三类:
第一类是由CPU外部引起的,称作中断,如I/O中断、时钟中断、控制台中断等;

中断类型概念
程序中断由指令执行的结果产生,如算数溢出、除数为0、试图执行非法指令
时钟中断由处理器内部的计时器产生,运行操作系统以一定的规律执行周期性的任务
I/O中断由I/O控制器产生,发信号通知一个io操作的正常完成或是错误
硬件失效中断如掉电或存储器奇偶校验之类的故障产生

第二类是来自CPU的内部事件或程序执行中的事件引起的过程,称作异常,如由于CPU本身故障(电源电压低于1.05V或频率在47~63Hz之外)、程序故障(非法操作码、地址越界、浮点溢出等)等引起的过程;
第三类由于在程序中使用了请求系统服务的系统调用而引发的过程,称作“陷入”(trap,或者陷阱)。

注意:前两类通常都称作中断,它们的产生往往是无意、被动的,而陷入是有意和主动的。

3.中断机制的基本原理

在这里插入图片描述

3.3 系统调用

记住下列事项是有益的。任何单CPU计算机一次只能执行一条指令。如果一个进程正在用户态运行一个用户程序,并且需要一个系统服务,比如从一个文件读数据,那么它就必须执行一个陷阱或系统调用指令,将控制转移到操作系统。操作系统接着通过参数检查找出所需要的调用进程。然后,它执行系统调用,并把控制返回给在系统调用后面跟随着的指令。在某种意义上,进行系统调用就像进行一个特殊的过程调用,但是只有系统调用可以进入内核,而过程调用则不能

在这里插入图片描述

什么是系统调用

知识点回顾:操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。其中,程序接口由一组系统调用组成。
在这里插入图片描述系统调用是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务

系统调用与库函数的区别

在这里插入图片描述

小例子:为什么操作系统是必须的

在这里插入图片描述

系统调用的过程

       为了使系统调用机制更清晰,我们简要地考察read系统调用。如上所述,它有三个参数:第一个参数指定文件,第二个指向缓冲区,第三个说明要读出的字节数。几乎与所有的系统调用一样,它的调用由C程序完成,方法是调用一个与该系统调用名称相同的库过程: read,由C程序进行的调用形式如下:
                                                                      count=read(fd, buffer, nbytes);
       系统调用(以及库过程)在count中返回实际读出的字节数。这个值通常和nbytes相同,但也可能更小,例如,如果在读过程中遇到了文件尾的情形就是如此。如果系统调用不能执行,不论是因为无效的参数还是磁盘错误, count都会被置为-1,而在全局变量errno中放入错误号,程序应该经常检查系统调用的结果,以了解是否出错。
       `系统调用是通过一系列的步骤实现的。为了更清楚地说明这个概念,考察上面的read调用。在准备调用这个实际用来进行read系统调用的read库过程时,

  • 调用程序首先把参数压进堆栈,如图1-17中步骤1~步骤3所示
    在这里插入图片描述

由于历史的原因, C以及C++编译器使用逆序(必须把第一个参数赋给printf (格式字符串),放在堆栈的顶部)。第一个和第三个参数是值调用,但是第二个参数通过引用传递,即传递的是缓冲区的地址(由&指示),而不是缓冲区的内容。

  • 第4步:对库过程的实际调用。这个指令是用来调用所有过程的正常过程调用指令。
  • 第5步:在可能是由汇编语言写成的库过程中,一般把系统调用的编号放在操作系统所期望的地方,如寄存器中
  • 第6步:执行一个TRAP指令,将用户态切换到内核态,并在内核中的一个固定地址开始执行

TRAP指令实际上与过程调用指令非常类似,它们后面都跟随一个来自远处位置的指令,以及供以后使用的一个保存在栈中的返回地址。
然而, TRAP指令与过程指令存在两个方面的差别。首先,它的副作用是,切换到内核态。而过程调用指令并不改变模式。其次,不像给定过程所在的相对或绝对地址那样, TRAP指令不能跳转到任意地址上。根据机器的体系结构,或者跳转到一个单固定地址上,或者指令中有一8位长的字段,它给定了内存中一张表格的索引,这张表格中含有跳转地址。

  • 第7步:跟随在TRAP指令后的内核代码开始检查系统调用编号,然后分派给正确的系统调用处理器。这通常是通过一张由系统调用编号所引用的、指向系统调用处理器的指针表来完成
  • 第8步:系统调用处理器运行
  • 第9步:一旦系统调用处理器完成其工作,控制可能会在跟随TRAP指令后面的指令中返回给用户空间库过程
  • 第10步:这个过程接着以通常的过程调用返回的方式,返回到用户程序
  • 第11步:为了完成整个工作,用户程序还必须清除堆栈,如同它在进行任何过程调用之后一样,假设堆栈向下增长,如经常所做的那样,编译后的代码准确地增加堆栈指针值,以便清除调用read之前压入的参数。在这之后,原来的程序就可以随意执行了。

在前面第9步中,我们提到“控制可能会在跟随TRAP指令后面的指令中返回给用户空间库过程”,这是有原因的。系统调用可能堵塞调用者,避免它继续执行。例如,如果试图读键盘,但是并没有任何键入,那么调用者就必须被阻塞。在这种情形下,操作系统会查看是否有其他可以运行的进程,稍后,当需要的输入出现时,进程会提醒系统注意,然后步骤9-步骤11会接着进行。

06:00和08:40王道讲解
在这里插入图片描述
在这里插入图片描述

什么功能要用到系统调用

       应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、1/0操作、文件管理等) ,都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。
在这里插入图片描述

  • 进程管理也称为CPU管理。进程管理的主要目的有3个:第一个是公平,即每个程序都有机会使用CPU。第二个是非阻塞(non-blocking),即任何程序不能无休止地阻挠其他程序的正常推进。如果一个程序在运行过程中需要输入输出或者因别的什么事情而发生阻塞,这个阻塞不能妨碍别的进程继续前进。就像人类世界,缺了谁地球照样旋转。第三个是优先级。即某些程序比另外一些程序优先级高。如果优先级高的程序开始运行,则优先级低的程序就要让出资源。
  • 内存管理主要是管理缓存、主存、磁盘、磁带等存储介质所形成的内存架构。内存管理的另一个目的是让很多程序共享同一个物理内存。这就需要对物理内存进行分割和保护,不让一个程序访问另一个程序所占的内存空间,专业术语称为运行时不能越界。
  • 存储管理通常也称为外存管理,它就是众所周知的文件系统了。文件系统的主要目的是将磁盘变成一个很容易使用的存储媒介以提供给用户使用。

这样我们在访问磁盘时无须了解盘的物理属性或数据在磁盘上的精确位置,诸如磁道、磁柱、扇面等。当然,文件系统还可以建立在光盘磁带上。只是使用最为频繁的文件系统都以磁盘为介质。

  • 设备管理也称为I/O管理,就是管理输入输出设备。I/O管理的目的有两个:一是屏蔽不同设备的差异性,即用户用同样的方式访问不同的设备,从而降低编程的难度;二是提供并发访问,即将那些看上去并不具备共享特性的设备(如打印机)变得可以共享。

但是在现代操作系统这本书,在POSIX系统中,系统调用被分为4类:

进程管理
调用说明
pid = fork()创建与父进程相同的子进程
pid = waitpid(pid, &statloc,options)等待一个子进程终止
s = execve(name, argv, environp)替换一个进程的核心映像
exit(status)终止进程执行并返回状态
文件管理
调用说明
fd = open(file, how,…)打开一个文件供读、写或两者
s=close(fd)n= read(fd, buffer, nbytes)关闭一个打开的文件
n = read(fd, buffer, nbytes)把数据从一个文件读到缓冲区中
n = write(fd, buffer, nbytes)把数据从缓冲区写到一个文件中
position =Iseek(fd, offset, whence)移动文件指针
s=stat(name, &buf)取得文件的状态信息
目录和文件系统管理
调用说明
s=mkdir(name, mode)创建一个新目录
s=rmdir(name)删去一个空目录
s=link(name1, name2)创建一个新目录项name2,并指向namel
s=unlink(name)删去一个目录项
s= mount(special, name, flag)安装一个文件系统
s=umount(special)卸载一个文件系统
杂项
调用说明
s= chdir(dirname)改变工作目录
s= chmod(name, mode)修改一个文件的保护位
s=kill(pid, signal)发送信号给一个进程
seconds =time(&seconds)自1970年1月1日起的流逝时间

       从广义上看,由这些调用所提供的服务确定了多数操作系统应该具有的功能,而在个人计算机上资源管理功能是较弱的(至少与多用户的大型机相比较是这样)。所包含的服务有创建与终止进程,创建删除读出和写人文件,目录管理以及完成输入输出。

       有必要指出,将POSIX 过程映射到系统调用并不是一对一的。POSIX标准定义了构造系统所必须提供的一套过程,但是并没有规定它们是系统调用、库调用还是其他的形式。如果不通过系统调用就可以执行一个过程(即无须陷入内核),那么从性能方面考虑,它通常会在用户空间中完成。不过,多数POSIX过程确实进行系统调用,通常是一个过程直接映射到一个系统调用上,在一些情形下,特别是所需要的过程仅仅是某个调用的变体时,一个系统调用会对应若干个库调用。

【综上所得】你就会发现,根据不同角度,系统调用可以分为不同的类别,但你只要知道系统调用的功能,牢牢把握根本就行。

操作系统体系结构

请添加图片描述
在这里插入图片描述

操作系统引导

开机的时候,让操作系统运行起来

磁盘里边有哪些相关数据

在这里插入图片描述

操作系统引导的过程

在这里插入图片描述

第二章 进程管理

从本章开始,我们将深入考察操作系统是如何设计和构造的。操作系统中最核心的概念是进程:这是对正在运行程序的一个抽象。操作系统的其他所有内容都是围绕着进程的概念展开的,所以,让操作系统的设计者(及学生)尽快并透彻地理解进程是非常重要的。即使可以使用的CPU只有一个,但它们也具有支持(伪)并发操作的能力,它们将一个单独的CPU变换成多个虚拟的CPU,没有进程的抽象,现代计算将不复存在
现在考虑只有一个用户的PC。当启动系统时,会秘密启动许多进程。例如,启动一个进程用来等待进入的电子邮件;或者启动另一个防病毒进程周期性地检查是否有病毒库更新。另外,某个用户进程可能会在所有用户上网的时候打印文件以及刻录CD-ROM。这些活动都需要管理,于是一个支持多进程的多道程序系统在这里就显得很有用了。
在任何多道程序设计系统中,CPU由一个进程快速切换至另一个进程,使每个进程各运行几十或几百毫秒。严格地说,在某一个瞬间,CPU只能运行一个进程。但在1秒钟内,它可能运行多个进程,这样就产生并行的错觉。有时人们所说的伪并行就是指这种情形,以此来区分多处理器系统(该系统有两个或多个CPU共享同一个物理内存)的真正硬件并行。

人们很难对多个并行活动进行跟踪,因此,经过多年的努力,操作系统的设计者开发了用于描述并行的一种概念模型(顺序进程),使得并行更容易处理。有关该模型、它的使用以及它的影响正是本章的主题。

2.1 进程

2.1.1 进程的概念、组成、特征

在这里插入图片描述

1.进程的概念

在进程模型中,计算机上所有可运行的软件,通常也包括操作系统,被组织成若干顺序进程(sequential process).简称进程(process).一个进程就是一个正在执行程序的实例,包括程序计数器寄存器和变量的当前值。从概念上说,每个进程拥有它自己的虚拟CPU。
当然,实际上真正的CPU在各进程之间来回切换。但为了理解这种系统,考虑在(伪)并行情况下运行的进程集,要比试图跟踪CPU如何在程序间来回切换简单得多。正如在第1章所看到的,这种快速的切换称作多道程序设计
在这里插入图片描述
进程与程序间的区别
进程和程序间的区别是很微妙的,但非常重要。
在这里插入图片描述

用一个比喻可以更容易理解这一点。想象一位有一手好厨艺的计算机科学家正在为他的女儿烘制生日蛋糕。他有做生日蛋糕的食谱,厨房里有所需的原料:面粉、鸡蛋、糖、香草汁等。在这个比喻中,做蛋糕的食谱就是程序(即用适当形式描述的算法)【可执行文件】,计算机科学家就是处理器(CPU),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和【程序的一次执行过程 】。
现在假设计算机科学家的儿子哭着跑了进来,说他的头被一只蜜蜂蛰了。计算机科学家就记录下他照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理蛰伤。这里,处理机从一个进程(做蛋糕)切换到另一个高优先级的进程(实施医疗救治),每个进程拥有各自的程序(食谱和急救手册),当蜜蜂蛰伤处理完之后,这位计算机科学家又回来做蛋糕,从他离开时的那一步继续做下去。
这里的【关键思想】是:一个进程是某种类型的一个活动,它有程序、输入、输出以及状态。单个处理器可以被若干进程共享,它使用某种调度算法决定何时停止一个进程的工作,并转而为另一个进程提供服务。
值得注意的是,如果一个程序运行了两遍,则算作两个进程。例如,人们可能经常两次启动同一个字处理软件,或在有两个可用的打印机的情况下同时打印两个文件。像“两个进程恰好运行同一个程序这样的事实其实无关紧要,因为它们是不同的进程。操作系统能够使它们共享代码,因此只有一个副本放在内存中,但那只是一个技术性的细节,不会改变有两个进程正在运行的概念。

2.进程的组成
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
举例:
在这里插入图片描述

在我们写完一个程序之后,经过编译链接等等一系列的步骤,最终会形成一个可执行文件,像大家熟悉的windows电脑里就是.exe的文件。那这个可执行文件平时是存放在硬盘当中,这个可执行文件当中保存的其实就是一系列的指令序列。而当这个程序要运行之前需要把它从硬盘读入到内存当中,并且操作系统会建立一个与它相对应的进程,并会建立相对应的pcb。这个程序的那一系列指令序列也需要读到内存当中,那这一系列的指令序列,我们把它称作为程序段
其实这个程序执行的过程,或者说这个进程,它执行的过程就是cpu从内存中读入这些一条一条的指令,然后来执行这些指令。除了执行这些指令之外,在执行指令的过程当中会有一些中间的数据,会有一个叫数据段的区域用来存放这个程序运行过程当中所产生、所需要使用的各种数据。

3.进程的特征

在这里插入图片描述

在这里插入图片描述

2.1.2 进程的状态与转换、进程的组织

在这里插入图片描述
1.进程的状态
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

进程状态的转换
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

进程的组织–链接方式
在这里插入图片描述
进程的组织–索引方式

在这里插入图片描述

2.1.3 进程控制

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
思考:如果这两个特权指令允许用户程序使用的话,会发生什么情况?
假设我在我的程序开头就植入一个关中断指令,程序结尾植入一个开中断指令,那么就意味着,程序一旦被CPU运行,就会一直霸占着CPU,中断不会执行,显然这种情况不应该让它发生。

进程控制相关的原语
进程的创建

操作系统需要有一种方式来创建进程。一些非常简单的系统,即那种只为运行一个应用程序设计的系统(例如,微波炉中的控制器),可能在系统启动之时,以后所需要的所有进程都已存在,然而,在通用系统中,需要有某种方法在运行时按需要创建或撤销进程,现在开始考察这个问题。
在这里插入图片描述

4种主要事件会导致进程的创建:

  • 1)系统初始化
    启动操作系统时,通常会创建若干个进程。其中有些是前台进程,也就是同用户(人类)交互并且替他们完成工作的那些进程。其他的是后台进程,这些进程与特定的用户没有关系,相反,却具有某些专门的功能。

例如,设计一个后台进程来接收发来的电子邮件,这个进程在一天的大部分时间都在睡眠,但是当电子邮件到达时就突然被唤醒了。也可以设计另一个后台进程来接收对该机器中Web页面的访问请求,在请求到达时唤醒该进程以便服务该请求,停留在后台处理诸如电子邮件、Web页面、新闻、打印之类活动的进程称为守护进程(daemon),在大型系统中通常有很多守护进程。在UNIX 中,可以用ps程序列出正在运行的进程;在Windows中,可使用任务管理器。

  • 2)正在运行的程序执行了创建进程的系统调用。
    除了在启动阶段创建进程之外,新的进程也可以以后创建。一个正在运行的进程经常发出系统调用,以便创建一个或多个新进程协助其工作。在所要从事的工作可以容易地划分成若干相关的但没有相互作用的进程时,创建新的进程就特别有效果。

例如,如果有大量的数据要通过网络调取并进行顺序处理,那么创建一个进程取数据,并把数据放入共享缓冲区中,而让第二个进程取走数据项并处理之,应该比较容易。在多处理机中,让每个进程在不同的CPU上运行会使整个作业运行得更快。

  • 3)用户请求创建一个新进程。
    在交互式系统中,键入一个命令或者点(双)击一个图标就可以启动一个程序。这两个动作中的任何一个都会开始一个新的进程,并在其中运行所选择的程序。在基于命令行的UNIX系统中运行程序X,新的进程会从该进程接管开启它的窗口,在Microsoft Windows中,多数情形都是这样的,在一个进程开始时,它并没有窗口,但是它可以创建一个(或多个)窗口,在UNIX和Windows系统中,用户可以同时打开多个窗口,每个窗口都运行一个进程。通过鼠标用户可以选择一个窗口并且与该进程交互,例如,在需要时提供输入。
  • 4)一个批处理作业的初始化。
    最后一种创建进程的情形仅在大型机的批处理系统中应用。用户在这种系统中(可能是远程地)提交批处理作业。在操作系统认为有资源可运行另一个作业时,它创建一个新的进程,并运行其输入队列中的下一个作业。
    在这里插入图片描述

从技术上看,在所有这些情形中,新进程都是由于一个已存在的进程执行了一个用于创建进程的系统调用而创建的。这个进程可以是一个运行的用户进程、一个由键盘或鼠标启动的系统进程或者一个批处理管理进程。这个进程所做的工作是,执行一个用来创建新进程的系统调用。这个系统调用通知操作系统创建一个新进程,并且直接或间接地指定在该进程中运行的程序。如上图:就反映了这些进程之间的父子关系,PID为0的进程创建了PID为1的进程,那么PID为0进程就是PID为1进程的父进程。

【扩充知识】
在UNIX系统中,只有一个系统调用可以用来创建新进程: fork。这个系统调用会创建一个与调用进程相同的副本。在调用了fork后,这两个进程(父进程和子进程)拥有相同的内存映像、同样的环境字符串和同样的打开文件。这就是全部情形。通常,子进程接着执行execve或一个类似的系统调用,以修改其内存映像并运行一个新的程序。例如,当一个用户在shell中键入命令sort时,shell就创建一个子进程,然后,这个子进程执行sort,之所以要安排两步建立进程,是为了在fork之后但在execve之前允许该子进程处理其文件描述符,这样可以完成对标准输入文件、标准输出文件和标准错误文件的重定向。
在Windows中,情形正相反,一个Win32函数调用CreateProcess既处理进程的创建,也负责把正确的程序装入新的进程。该调用有10个参数,其中包括要执行的程序、输入给该程序的命令行参数、各种安全属性、有关打开的文件是否继承的控制位、优先级信息、该进程(若有的话)所需要创建的窗口规格以及指向一个结构的指针,在该结构中新创建进程的信息被返回给调用者。除了CreateProcess,Win32中有大约100个其他的函数用于处理进程的管理、同步以及相关的事务
在UNIX和Windows中,进程创建之后,父进程和子进程有各自不同的地址空间。如果其中某个进程在其地址空间中修改了一个字,这个修改对其他进程而言是不可见的。在UNIX中,子进程的初始地址空间是父进程的一个副本,但是这里涉及两个不同的地址空间,不可写的内存区是共享的。某些UNIX的实现使程序正文在两者间共享,因为它不能被修改。或者,子进程共享父进程的所有内存,但这种情况下内存通过写时复制(copy-on-write)共享,这意味着一旦两者之一想要修改部分内存,则这块内存首先被明确地复制,以确保修改发生在私有内存区域。再次强调,可写的内存是"不可以共享"的。但是,对于一个新创建的进程而言,确实有可能共享其创建者的其他资源,诸如打开的文件等。在Windows中,从一开始父进程的地址空间和子进程的地址空间就是不同的。

进程的终止

在这里插入图片描述
进程在创建之后,它开始运行,完成其工作。但永恒是不存在的,进程也一样。迟早这个新的进程会终止,通常由下列条件引起:

  • 1)正常退出(自愿的)
    多数进程是由于完成了它们的工作而终止。当编译器完成了所给定程序的编译之后,编译器执行一个系统调用,通知操作系统它的工作已经完成。

在UNIX中该调用是出口,而在Windows中,相关的调用是ExitProcess,面向屏幕的程序也支持自愿终止。字处理软件,网络浏览器和类似的程序中总有一个供用户点击的图标或菜单项,用来通知进程删除它所打开的任何临时文件,然后终止

  • 2)出错退出(自愿的)
    进程终止的第二个原因是进程发现了严重错误。例如,如果用户键入命令cc foo.c要编译程序foo.c,但是该文件并不存在,于是编译器就会退出。在给出了错误参数时,面向屏幕的交互式进程通常并不退出。相反,这些程序会弹出一个对话框,并要求用户再试一次。
  • 3)严重错误(非自愿)
    进程终止的第三个原因是由进程引起的错误,通常是由于程序中的错误所致。例如,执行了一条非法指令,引用不存在的内存,或除数是零等。有些系统中(如UNIX),进程可以通知操作系统,它希望自行处理某些类型的错误,在这类错误中,进程会收到信号(被中断),而不是在这类错误出现时终止。
  • 4)被其他进程杀死(非自愿)
    第四种终止进程的原因是,某个进程执行一个系统调用通知操作系统杀死某个其他进程。在UNIX中,这个系统调用是kill。在Win32中对应的函数是TerminateProcess,在这两种情形中,“杀手”都必须获得确定的授权以便进行动作。在有些系统中,当一个进程终止时,不论是自愿的还是其他原因,由该进程所创建的所有进程也一律立即被杀死,不过,UNIX和Windows都不是这种工作方式。
进程的阻塞和切换

在这里插入图片描述
进程运行的环境
在这里插入图片描述

进程的切换

在这里插入图片描述

在这里插入图片描述

2.1.4 进程通信

进程间通信(Inter-Process Communication, IPC)是指两个进程之间产生数据交互。
在这里插入图片描述

在这里插入图片描述
为什么进程通信需要操作系统支持?
系统当中给各个进程分配内存地址空间的时候,各个进程的这个内存地址空间是相互独立的,是不能访问不属于自己的内存空间。这么规定是出于安全的考虑,如果一个进程可以随意的访问其他进程的内存地址空间,那么这个进程就可以随便修改其它进程的数据了或者随意的读取其它进程的数据,比如读取你的聊天记录等,这显然是很危险的。所以各进程拥有各自独立的内存空间。由于进程不能随意访问其它进程的内存空间,所以就必须要有操作系统的支持,才可以完成进程之间的通信。

共享存储

在这里插入图片描述
互斥(mutual exclusion),即以某种手段确保当一个进程在使用一个共享变量或文件时,其他进程不能做同样的操作。
在这里插入图片描述

消息传递

在这里插入图片描述
上面提到的其他的方法就是消息传递(message passing)。这种进程间通信的方法使用两条原语send和receive,它们像信号量而不像管程,是系统调用而不是语言成分。因此,可以很容易地将它们加入到库例程中去。例如:
send(destination, &message);
调用向一个给定的目标发送一条消息,
receive(source, &message);
调用从一个给定的源(或者是任意源,如果接收者不介意的话)接收一条消息。如果没有消息可用,则接收者可能被阻塞,直到一条消息到达,或者,带着一个错误码立即返回。

直接通信方式:
在这里插入图片描述

间接通信方式:

在这里插入图片描述

管道通信

在这里插入图片描述
在这里插入图片描述

2.2 线程

在这里插入图片描述

2.1_5_ 线程的概念

2.1_6_线程的实现方式和多线程模型

2.1_7_线程的状态与转换

2.2_1_调度的概念、层次

2.2_2_进程调度的时机、切换与过程、方式

2.2_3_调度器和闲逛进程

2.2_4_调度算法的评价指标

2.2_5_调度算法

2.2_6_调度算法

2.5 经典的IPC问题

第三章

  • 26
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值