进程:
为了使程序并发执行,我们引入了进程
程序段、数据段、PCB便构成了进程实体。
PCB用于描述进程的基本情况和活动状态
进程是程序的一次执行
进程是程序及其数据在处理机上顺序执行发生的活动。
进程是具有独立功能的程序在一个数据集合上运行的过程,他是系统进行资源分配和调度的一个独立单位
进程有一定生命周期,而程序是一组有序指令的集合
程序没有pc是不能参与并发执行的
进程的状态:
就绪状态:指进程已经处于准备好的运行状态,即进程已经分配到除cpu以外的必要资源后,只要再获得cpu,便可立即执行,
如果系统中有许多就绪状态的进程会将他们按照一定策略排为一个名为就绪队列的队列
执行状态:指进程已经获得CPU,程序处于正在执行状态
阻塞状态:正在执行的程序由于发生了某事件(I/O请求,申请缓冲区失败等)暂时无法继续执行的状态。此时引起进程调度,OS把处理机分配给另一个就绪进程,而让受阻线程处于处于暂停状态。通常阻塞线程也排成一个队列名为阻塞队列,在较大的系统上为了减少队列操作的开销,根据阻塞原因不停设置多个阻塞队列。
当然还有创建状态和终止状态
创建:申请空的pcb,并且向tcp中填写用于控制的管理和控制进程的信息;然后为该进程分配运行时所需的资源,最后把该进程转入就绪状态并插入就绪队列。
终止:pcb清零并返还给系统,当进程到达了结束点、出现了无法克服的错误、或者被操作系统终结,进入终止状态。进入后不能执行,但仍保留一个记录,供其他线程收集,完成后删除线程。
在许多系统中还引入了挂起状态:
挂起使此进程处于禁止状态,与挂起相对应的是激活
挂起的原因:用户的需要、父进程请求紫禁城挂起对其研究或者修改、负荷调节
引入挂起后的几个状态的转换
活动就绪-静止就绪:静止就绪的线程不能被调度,必须激活
活动阻塞-静止阻塞:原本是阻塞被挂起够变为静止阻塞。
创建-静止就绪:考虑到当前资源状况和性能要求不分配给新建进程所需资源。
进程同步:
使用互斥的方法完成进程同步:
1.间接相互制约关系:如打印机这种,用户申请使用时应先提出申请
2.直接相互制约关系:两个线程相互合作,必须等待线程a完成才能运行线程b
临界资源:就是互斥的访问某个资源
临界区:把在每个进程中访问临界资源的那段代码称为临界区。
消费生产者问题:
生产者生产数据到缓冲区中,消费者从缓冲区中取数据。
如果缓冲区已经满了,则生产者线程阻塞;
如果缓冲区为空,那么消费者线程阻塞。
两者不能同时操作,需要加锁,这样缓冲区作为临界资源互斥访问
哲学家进餐问题:
有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。
在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子又继续思考。
哲学家进餐问题可看作是并发进程并发执行时处理共享资源的一个有代表性的问题。
此算法可以保证不会有相邻的两位哲学家同时进餐。
若五位哲学家同时饥饿而各自拿起了左边的筷子,这使五个信号量 chopstick 均为 0,当他们试图去拿起右边的筷子时,都将因无筷子而无限期地等待下去,即可能会引起死锁。
- 方法一:至多只允许四位哲学家同时去拿左筷子,最终能保证至少有一位哲学家能进餐,并在用完后释放两只筷子供他人使用。
- 方法二:仅当哲学家的左右手筷子都拿起时才允许进餐。
- 方法三:规定奇数号哲学家先拿左筷子再拿右筷子,而偶数号哲学家相反。
-
方法三
规定奇数号哲学家先拿左筷子再拿右筷子,而偶数号哲学家相反。
原理:按照下图,将是 2,3 号哲学家竞争 3 号筷子,4,5 号哲学家竞争 5 号筷子。1 号哲学家不需要竞争。最后总会有一个哲学家能获得两支筷子而进餐。
读者-写者问题:
计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:
(1)允许多个读者同时执行读操作;
(2)不允许读者、写者同时操作;
(3)不允许多个写者同时操作。
进程通信:
用于进程间交换信息
一、管道
管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。
1、特点:
-
它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
-
它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
-
它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
二、FIFO
FIFO,也称为命名管道,它是一种文件类型。
1、特点
-
FIFO可以在无关的进程之间交换数据,与无名管道不同。
-
FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
三、消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
1、特点
-
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
-
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
-
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取。
四、信号量
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
1、特点
-
信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
-
信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
-
每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
-
支持信号量组。
五、共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
1、特点
-
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
-
因为多个进程可以同时操作,所以需要进行同步。
-
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
线程:
为了使多个程序并发执行,以提高资源利用率和系统吞吐量,进程同时拥有资源并且作为调度和分派的基本单位,我们想要将这两个属性分开
那么操作系统中引入进程为了减少程序在并法执行所付出的时空开销,作为调度和分派的基本单位,使OS具有更好的并发性。
进程又称为重型进程,线程又称为轻型线程
引入线程后:
进程仍是一个可拥有资源的基本单位。
一个进程通常含有若干个线程,至少为一个
进程已经不是可执行的实体,线程作为执行的基本单位
问:
1、什么是进程、线程,两者的关系?
答:程序是一组静态的指令集合
进程的来源:
这个时候人们就发明了进程,用进程来对应一个程序,每个进程对应一定的内存地址空间,并且只能使用它自己的内存空间,各个进程间互不干扰。并且进程保存了程序每个时刻的运行状态,这样就为进程切换提供了可能。当进程暂时时,它会保存当前进程的状态(比如进程标识、进程的使用的资源等),在下一次重新切换回来时,便根据之前保存的状态进行恢复,然后继续执行。
在未引入线程前:
进程是程序及其数据在处理机上顺序执行发生的活动。同时她是系统进行分配资源和调度的基本单位,进程有一定的生命周期
在引入线程后:
为了解决程序在并发执行付出的开销,我们将进程从原来作为系统调度的基本单位这一功能解放出来,在线程里引入线程,线程是进程中的一部分,一个进程可以有多个进程,最少一个。让线程成为系统调度的基本单位并且基本不具备数据,那么这样切换线程的效率将会比切换进程的效率高的多,
调度算法:
作业调度(高级调度):调度对象是作业。其主要功能是将外存上处于后备队列中的哪几个作业调入内存,为他们创建进程、分配必要的资源。并将它们放入就绪队列
作业调度的算法:
先来先服务(FCFS):
系统将按照作业到达的先后次序来进行调度,该进程一直运行到完成或发生某事件阻塞后,进程才将处理机分配给其他进程
短作业优先(SJF):
作业越短优先级越高,它将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将他们调入内存
缺点:必须预知作业的运行时间,如果估计时间太低,导致作业未完成就终止
对长时间作业不利,可能一直等待。
优先级调度算法(PSA):
基于作业的紧迫程度,由外部赋予作业相应的优先级。,根据该优先级调度
高响应比优先调度算法(HRRN)
既考虑了作业的等待时间,又考虑了作业运行时间的调度算法。
通过优先权=(等待时间+要求服务时间)/要求服务时间,那么服务时间短的先运行,然后是等待时间过长的优先级也会升高,优先级也会变大
进程调度(低级调度)
其所调度的对象是进程,根据某种算法,决定就绪队列中的那个进程应该获得处理机,并由分派程序将处理机分配给进程。
进程调度算法:
分为两种类型:
非抢占式:将处理机分配给进程后,由该进程独占,直到完成或者阻塞
抢占类型:允许暂停某个正在执行的线程,将已分配给该进程的处理机重新分配给另一个线程
调度算法:
轮转调度算法:
按照先来先服务的原则排成队列,让就绪队列上的每个进程每次仅运行一个时间片
切换:
若一个时间片该进程已经完成,则从就绪队列中删除它,再选队首
如果时间片结束进程未完。则将其放入就绪队列末尾。
优先级调度算法:
非抢占式:一旦处理分配给就绪队列中优先级高的进程,该进程一直执行下去到完成
抢占式优:先分配给队列中优先级高的线程,如果有更高的优先级线程出现,则切换至优先级更高的线程执行
多队列调度算法:
将进程中就绪队列从一个拆分成多个,将不同类型或者性质的进程固定分配在不同的就绪队列,不同的队列可采用不同的调度算法
多级反馈队列:
设置多个就绪队列,每个队列赋予不同的优先级,优先级越高时间片越小,,每个队列采用先来先服务的算法,如何一个时间片未执行完成,我们将它放入下个队列尾部,,知道完成,并且调度时按队列优先级调度,当第一队列空闲时才向下调用,如果调用程序在处理进程时,其上级队列来了新的进程,那么必须转为调用新来的优先级高的进程。
什么是死锁?死锁产生的条件?
在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
死锁产生的四个条件(有一个条件不成立,则不会产生死锁)
- 互斥条件:一个资源一次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
- 不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系
预防死锁:
- 资源一次性分配:(破坏请求和保持条件)
- 可剥夺资源:即当某进程新的资源未满足时,释放已占有的资源(破坏不可剥夺条件)
- 资源有序分配法:将系统中的所有资源统一编号,进程可在任何时刻提出资源申请,但所有申请必须按照资源的编号顺序(升序)提出。
存储器:
高速缓存:
由于主存储器访问速度远低于CPU执行指令速度,引入告诉缓存缓和这一矛盾,
他主要用于备份主存中常用的数据,减少处理机对主存储器的访问次数,大幅度地提高程序执行速度。,当CPU访问一组特定信息时,先检查它是否在高速缓存中,如果在,便直接取出使用,避免对主存的访问。
磁盘缓存:
由于当前的磁盘的I/O速度远低于对主存的访问速度,为了缓和两者之间对速度的匹配,设置了磁盘缓冲
用于存放频繁使用的一部分磁盘数据和信息,减少访问磁盘次数,旦磁盘缓冲并不实际存在,它是利用主存的部分存储信息。
对换:
在多道程序中,在内存中某些进程由于某事件尚未发生而被阻塞,但他却占用了大量的内存空间。其他作业可能因为内存空间不足而无法调入内存。为了解决这一问题引入对换,把暂时不用的数据换出到外村上,腾出足够的空间
如果使用连续分配方式内存会产生很多内存碎片:
分页式存储管理:
页的大小和段的大小一般相同,当然页的大小也可以设置小于段的大小。
连续分配方式产生内存碎片的原因就是因为有时候程序需要的内存并没有分好区的内存大,那么就会产生内存碎片,我们将一个进程分散的装入许多不相邻的分区中,便可充分利用内存
实现:
我们首先将进程的逻辑地址分为若干个页,并给每个页编号,成为页号,然后给内存物理地址编号成为块号,给它们也编号,在为进程分配内存时,以块为单位,将内存的若干页装入不同的块中,那么就完成了,由于内存中的最后一页通常装不满一个块,形成了不可用的碎片称为“页内碎片”。
页面大小的设置:
页面设置过小:减少了内存碎片,但是页面过多占用大量内存
页面设置过大:占用的内存变少了,但是使内存碎片增大。
页表:
那么我们如何通过页面去找到内存呢。,系统为每个进程创建了一张页面映像表,简称页表,其中记录了相应页在内存中对应的物理块号。完成了页号到物理块号的映射。
为了将逻辑地址变为物理地址,将页号和块号设置大小相同,那么直接将逻辑页号转为物理块号就行了
两级和多级页表:
为了解决页表过大的情况,我们引入了多级页表这里以二级页表做演示
我们的外层页表的表项中所存放的是某页表分页的首址。如图
分段式存储管理 :
由于通常的程序都是可以分为若干个段的,如主程序段、子程序段A、子程序段B、数据段等,每个段大多是一个独立的逻辑单元,因此我们将程序分段进行存储、
分段的实现也很简单:
我们为每个分段都分配一个连续的分区,进程中的各段,可以离散地装入内存中的不同分区。
为了保证能程序能正常运行,建立一个段表存储了逻辑段到物理地址的映射
如图:段号记录相应的分区,并且记录逻辑段长度和这段在物理内存中的起始地址。
分页和分段的区别:
分页式是为了消除内存的零头,提高内存的利用率
因为段是信息的逻辑单位,通常包含一组意义相对完整的信息。分段式是为了更好的满足用户的需求
段页式存储管理方式:
我们将两种结合。
首先先将用户程序分为若干个段,再把每个段分为若干页,给每个段赋予一个段名:
如图。我们每个段都有一个段号,根据段号找到这个段分的页表,然后再找到相应的物理地址。
结合两者优点,即省空间,又能满足用户的需求
虚拟存储器(虚拟内存)
为什么需要:
有的作业很大,其所要求的内存空间超过了内存总容量,作业不能全部装入内存,致使作业无法运行
有大量作业要求运行,但由于内存容量不足以容纳这些作业,只能将少数作业装入内存让他们先运行,而将其他大量的作业留在外存上等待。
虚拟存储器工作形式:
应用程序在运行之前没必要将之全部装入内存,而需要将那些当前要运行的少数页面或者段先装入内存便可运行,其余暂时留在硬盘。如果它要访问的页(段)已调入内存,便可继续执行,如果所要访问的页或者段没有调入内存,便发出缺页(段)请求。
此时OS将利用请求调页(段)功能将他们调入内存,以使进程能继续执行下去,如果内存已满,还需要利用页(段)的置换功能,将内存中暂时不用的页(段)调至盘上,腾出足够内存空间,再将需要的页(段)调入内存。使程序继续执行下去。
所以:虚拟存储器是指具有请求调入和置换功能,能从逻辑上扩展内存容量加以扩充的一种存储器系统。
页面调入策略:、
页面置换算法:
先进先出页面置换算法:
总是淘汰最先进入内存的页面,就是选择内存中驻留时间最久的页面予以淘汰。
缺点:但是有的老页面最先被访问,但是却经常被使用到,如全局变量、常用函数,fifo无法保证这种页面不被淘汰
优点:实现简单
LRU置换算法:
选择最近最久的页面予以淘汰,该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间,当需要淘汰一个页面时选择t最大的淘汰
缺点:硬件支持过多
由于LRU硬件支持过多
引入了Clock算法:
我们给每页设置一个访问位。将所有页面都通过链接指针连接成一个循环队列,每当页被访问时,访问位置为1,再选择某页淘汰时,判断其访问位是否为0,为0淘汰,为1则置为0。给与第二次驻留内存的机会。然后通过fifo算法检查下一个页面(这里的fifo不是判断页,而是找到下一个页用fifo,就是根据进入顺序找到页),当检查到最后一个页面时,再去第一个页面继续检查。
页面缓冲算法:
影响页面换进换出的效率包括:页面置换算法、将修改页面写会磁盘的效率
因此我们在系统中建立一个已经修改换出页面的链表,则对每一个要被换出的页面,系统可暂不把他们写回磁盘,而是将他们挂在已修改换出页面的链表上,仅当被换出页面数目达到一定值,才写入磁盘
这样即减少了磁盘写入的次数,并且当这些链表页面再次被取出时,不需要去磁盘读,直接去链表里读取即可。减少了将页面读入内存的频率。
简单来说:降低了页面换进换出的频率和想磁盘写入修文件的次数。
抖动:
在系统中运行的进程太多,因此给每个进程分配的物理块太少,不能满足进程正常运行的基本要求,致使每个进程运行时,频繁出现缺页。必须请求系统将所缺页面调入内存,这会使得在系统中排队等待页面调进/调出的进程数目增多。造成每个进程大部分时间都用于换进换出。而不能去做任何有效的工作。