您现在的位置是:主页 > news > 怎样设计网站建设/百度seo优化分析
怎样设计网站建设/百度seo优化分析
admin2025/5/14 0:20:28【news】
简介怎样设计网站建设,百度seo优化分析,网站安全维护公司,可以自己做图的网站2.操作系统 2.1 进程和线程的区别 进程可以说是一个“执行中的程序”。程序是指令、数据及其组织形式的描述,是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,…
2.操作系统
2.1 进程和线程的区别
进程可以说是一个“执行中的程序”。程序是指令、数据及其组织形式的描述,是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。
有了线程技术,我们就可以在一个进程中创建多个线程,让它们在“同一时刻”分别去做不同的工作了。这些线程共享同一块内存,线程之间可以共享对象、资源,如果有冲突或需要协同,还可以随时沟通以解决冲突或保持同步。
不过,多线程技术不是万金油,它有一个致命的缺点:在一个进程内,不管你创建了多少线程,它们总是被限定在一颗CPU内,或者多核CPU的一个核内。这意味着,多线程在宏观上是并行的,在微观上则是分时切换串行的,多线程编程无法充分发挥多核计算资源的优势。这也是使用多线程做任务并行处理时,线程数量超过一定数值后,线程越多速度反倒越慢的原因。
多进程技术正好弥补了多线程编程的不足,我们可以在每一颗CPU上,或者多核CPU的每一个核上启动一个进程,如果有必要,还可以在每个进程内再创建适量的线程,最大限度地使用计算资源解决问题。因为不在同一块内存区域内,和线程相比,进程间的资源共享、通信、同步等,都要麻烦得多,受到的限制也更多。
总结:
- 线程在进程下行进(单纯的车厢无法运行)
- 一个进程可以包含多个线程(一辆火车可以有多个车厢)
- 不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
- 同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
- 进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
- 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
- 进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
- 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-“互斥锁”
- 进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”
2.2 进程调度的算法
1.先来先服务(FCFS):
每个进程按进入内存的时间先后排成一队。每当 CPU 上的进程运行完毕或者阻塞,选择队伍最前面的进程,然后 CPU 执行。
这一算法听起来简单又公平,但是短进程的响应时间太长了,用户交互体验会变差。
2.短作业优先算法(SPN)
每次选择预计处理时间最短的进程。因此,在排队的时候,把短进程从队列里提到前面。短进程得到了很好的照顾,进程的平均响应时间大大降低。
但是长进程们不干了:短进程插队,导致他们经常得不到 CPU 资源,造成了「饥饿」现象。
这可是个大问题。FCFS 虽然响应时间长,但最后所有进程一定有使用 CPU 资源的机会。但 SPN 算法就不一样了,如果短进程源源不断加入队列,长进程们将永远得不到执行的机会——太可怕了。
3.短进程优先算法(HRRN)
综合考量进程的两个属性:等待时间和要求服务时间——等待时间长,要求服务时间短(就是短进程)的进程更容易被选中。
为了量化,我们制定了一个公式:响应比 = (等待时间+要求服务时间)/ 要求服务时间。响应比高的算法会先执行。我们称之为「高响应比优先」
4.时间片轮转算法(VRR)
在这个算法里,每个进程将轮流使用 CPU 资源,只不过在他们开始运行时,会为他们打开定时器,如果定时器到时间(或者执行阻塞操作),进程将被迫「下机」,切换至下一个进程。至于下一个进程的选择,直接用 FCFS 就好了。
时间片越短,固定时间里可运行的进程就越多,可 CPU 说过,切换进程是要消耗他不少指令周期的,时间片过短会导致大量 CPU 资源浪费在切换上下文上。时间片过长,短交互指令响应会变慢。所以具体怎么取,还得看交互时间大小
同时造成了I/O 密集型进程的问题,调度器时间片轮转没有照顾到我们这类进程啊!经常在 CPU 没呆到一半时间片,就遇到了阻塞操作,而且在阻塞队列,往往要停留很长时间。等阻塞操作结束,还得在就绪队列排好长时间队。那些处理器密集型进程,使用了大部分的处理器时间,导致I/O 密集型进程性能降低,响应时间跟不上”
考虑到这些进程的要求,操作系统决定为创建一个新的辅助队列。阻塞解除的进程,将进入这个辅助队列,进行进程调度时,优先选择辅助队列里的进程。
5. 优先级调度
每个进程将被赋予一个优先级,自己根据自己的情况确定优先级数值,但是,用户进程的优先级不准高于内核进程的优先级。
切换程序的时候,我会从优先级 1 的队列里选择一个进程,如果优先级 1 队列为空,才会选择优先级 2 中的进程,以此类推。
当然,为了保证低优先级进程不会饥饿,会优先调高等待时间长的进程的优先级。
不过使用这个算法,不仅需要大量切换进程,还需要动态调节优先级。
2.3 进程间的通信方式
1.无名管道( pipe ): 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2.高级管道(popen): 将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。
3.有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
4.消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5.信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
6.信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
7.共享内存( shared memory ) : 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
8.套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
管道:速度慢,容量有限
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
信号量:不能传递复杂信息,只能用来同步
共享内存:能够很容易控制容量,速度快,但要保持同步
2.4 进程具有的特征
- 动态性——进程的实质是程序在多道程序系统中的一次执行过程,既然是过程就要有始有终,所以进程会产生、会消亡。进程执行完毕后,一般不会留下关于它运行的一丝痕迹;
- 并发性——任何进程都可以同其他进程一起并发执行,并发是任意时刻只有一个程序在运行(要与并行相区别);
- 独立性——进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
- 异步性——由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。
2.5 线程的特征
1. 线程的含义
线程是程序执行流的最小单元,是被系统独立调度和分派的基本单位。
如同进程是一种抽象一样,线程也是一种抽象,一种更高度的抽象。原先一个进程只能同时完成一种任务,现在需求多了,促使一个进程要同时完成多个任务,如果没有线程的概念,那么同一进程内的任务只能串行运行(按序运行)。
现在,把进程也看作一个系统,那么进程的“进程”就是线程了。进程原先作为任务调度的基本单位,与线程相比,进程太“大”了,所以相比较而言,线程的粒度更小。
2. 线程的状态
线程的状态与进程的状态一样,也是五态模型,可以参照进程的五态模型。
3. 线程的特点
- 线程是操作系统调度的基本单位;
- 线程的状态切换比进程更迅速且开销更小;
- 线程不拥有资源,只是任务的一种抽象,同一进程内的线程共享该进程的资源;
- 对单核CPU而言,同一时刻只能运行一个线程;
- 一个进程至少有一个线程,且是它的主线程。
4. 线程的优点
- 充分利用CPU资源(如下的超线程技术会提到这点);
- 实现了进程内并发,使用任务的粒度分得更细,有利于开发人员对任务的分解、抽象(分解与抽象原则);
- 实现了进程内异步事件的处理,尤其是GUI事件、服务端应用等;
- 提高了程序的运行效率。
2.6 线程间的通信机制
线程间的通信方式:简单讲就是在锁、堆里的对象包括普通对象个原子变量,他们之间可以实现线程间的通信。
1、通过共享对象通信
线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里读取hasDataToProcess这个成员变量。线程A和B必须获得指向一个MySignal共享实例的引用,以便进行通信。如果它们持有的引用指向不同的MySingal实例,那么彼此将不能检测到对方的信号。需要处理的数据可以存放在一个共享缓存区里,它和MySignal实例是分开存放的。
2、忙等待(Busy Wait)
准备处理数据的线程B正在等待数据变为可用。换句话说,它在等待线程A的一个信号,这个信号使hasDataToProcess()返回true,线程B运行在一个循环里,以等待这个信号。
3、wait(),notify()和notifyAll()
忙等待没有对运行等待线程的CPU进行有效的利用,除非平均等待时间非常短。否则,让等待线程进入睡眠或者非运行状态更为明智,直到它接收到它等待的信号。
Java有一个内建的等待机制来允许线程在等待信号的时候变为非运行状态。java.lang.Object 类定义了三个方法,wait()、notify()和notifyAll()来实现这个等待机制。
一个线程一旦调用了任意对象的wait()方法,就会变为非运行状态,直到另一个线程调用了同一个对象的notify()方法。为了调用wait()或者notify(),线程必须先获得那个对象的锁。也就是说,线程必须在同步块里调用wait()或者notify()。以下是MySingal的修改版本——使用了wait()和notify()的
等待线程将调用doWait(),而唤醒线程将调用doNotify()。当一个线程调用一个对象的notify()方法,正在等待该对象的所有线程中将有一个线程被唤醒并允许执行(校注:这个将被唤醒的线程是随机的,不可以指定唤醒哪个线程)。同时也提供了一个notifyAll()方法来唤醒正在等待一个给定对象的所有线程。
如你所见,不管是等待线程还是唤醒线程都在同步块里调用wait()和notify()。这是强制性的!一个线程如果没有持有对象锁,将不能调用wait(),notify()或者notifyAll()。否则,会抛出IllegalMonitorStateException异常。
但是,这怎么可能?等待线程在同步块里面执行的时候,不是一直持有监视器对象(myMonitor对象)的锁吗?等待线程不能阻塞唤醒线程进入doNotify()的同步块吗?答案是:的确不能。一旦线程调用了wait()方法,它就释放了所持有的监视器对象上的锁。这将允许其他线程也可以调用wait()或者notify()。
一旦一个线程被唤醒,不能立刻就退出wait()的方法调用,直到调用notify()的线程退出了它自己的同步块。换句话说:被唤醒的线程必须重新获得监视器对象的锁,才可以退出wait()的方法调用,因为wait方法调用运行在同步块里面。如果多个线程被notifyAll()唤醒,那么在同一时刻将只有一个线程可以退出wait()方法,因为每个线程在退出wait()前必须获得监视器对象的锁。
4、丢失的信号(Missed Signals)
notify()和notifyAll()方法不会保存调用它们的方法,因为当这两个方法被调用时,有可能没有线程处于等待状态。通知信号过后便丢弃了。因此,如果一个线程先于被通知线程调用wait()前调用了notify(),等待的线程将错过这个信号。这可能是也可能不是个问题。不过,在某些情况下,这可能使等待线程永远在等待,不再醒来,因为线程错过了唤醒信号。
为了避免丢失信号,必须把它们保存在信号类里。在MyWaitNotify的例子中,通知信号应被存储在MyWaitNotify实例的一个成员变量里。
留意doNotify()方法在调用notify()前把wasSignalled变量设为true。同时,留意doWait()方法在调用wait()前会检查wasSignalled变量。事实上,如果没有信号在前一次doWait()调用和这次doWait()调用之间的时间段里被接收到,它将只调用wait()。
(校注:为了避免信号丢失, 用一个变量来保存是否被通知过。在notify前,设置自己已经被通知过。在wait后,设置自己没有被通知过,需要等待通知。)
5、假唤醒
由于莫名其妙的原因,线程有可能在没有调用过notify()和notifyAll()的情况下醒来。这就是所谓的假唤醒(spurious wakeups)。无端端地醒过来了。
如果在MyWaitNotify2的doWait()方法里发生了假唤醒,等待线程即使没有收到正确的信号,也能够执行后续的操作。这可能导致你的应用程序出现严重问题。
为了防止假唤醒,保存信号的成员变量将在一个while循环里接受检查,而不是在if表达式里。这样的一个while循环叫做自旋锁*(校注:这种做法要慎重,目前的JVM实现自旋会消耗CPU,如果长时间不调用doNotify方法,doWait方法会一直自旋,CPU会消耗太大)*。被唤醒的线程会自旋直到自旋锁(while循环)里的条件变为false。
留意wait()方法是在while循环里,而不在if表达式里。如果等待线程没有收到信号就唤醒,wasSignalled变量将变为false,while循环会再执行一次,促使醒来的线程回到等待状态。
6、多个线程等待相同信号
如果你有多个线程在等待,被notifyAll()唤醒,但只有一个被允许继续执行,使用while循环也是个好方法。每次只有一个线程可以获得监视器对象锁,意味着只有一个线程可以退出wait()调用并清除wasSignalled标志(设为false)。一旦这个线程退出doWait()的同步块,其他线程退出wait()调用,并在while循环里检查wasSignalled变量值。但是,这个标志已经被第一个唤醒的线程清除了,所以其余醒来的线程将回到等待状态,直到下次信号到来。
2.7 同步与异步
1. 同步的含义
同步,简单地说,就是调用一个过程时,假如过程还在执行状态,没有返回结果,那么在该过程返回之前,就不能继续做下一件事情。
举个例子来说,比如要先穿袜子再穿鞋,顺序不能颠倒,所以我概括同步的特点就是:顺序性、确定性、简易性。
- 顺序性,就是运行次序不会颠倒错乱,一切按顺序来;
- 确定性,就是运行顺序是确定的,可以预见的,就像数学的计算过程一样,最后的答案是确定的;
- 简易性,因为同步不牵涉到线程的概念,运行一个简单的单线程程序时,不会用到系统提供的线程同步机制(API)
2. 异步的含义
异步是相对于同步而言的,意思与同步相反。即调用一个过程时,就接着做下面的事情,不立即获得该过程的返回值。
打个比方,用微波炉加热食物,按下“启动”键,微波炉就开始运行了。这时,你不会去苦苦等待它加热,可以做其他的事情。等到听到一声“叮”时,你知道加热完毕了,就会去拿出食物。
这里涉及到几个细节:你去干别的事、听到“叮”的一声就跑过去。
你去做别的事,那么现在一共有两件事正在做的过程当中,抽象成线程,就是两个线程在同时运行;
听到“叮”的一声就跑过去,说明过程返回了,但你并没有苦苦等这个过程返回,这个“返回”是巧妙的。
因此,要实现异步,你得学会做两件事——添加新任务(创建线程),知道旧任务已经结束了并跑去处理(状态、通知和回调)。
3 实现异步的方法
创建线程可以通过调用API来实现,那么怎么知晓旧任务已经运行结束了呢?
- 状态,即设一共享变量(FLAG),旧任务结束时,变量置有效值,之后旧任务结束,新任务循环检测变量是否有效;
- 通知,即像下载软件一样,下载完,系统会通知你,即旧任务向新任务发通知或消息,发完之后,旧任务结束;
- 回调,就是把旧任务做完后要做的收尾工作交给旧任务本身,这样,旧任务做完收尾工作后便结束。
上述三种方法当中,“回调”,旧任务与新任务之间没有关系;“通知”,旧任务和新任务有直接联系;“状态”,旧任务和新任务有间接联系,通过状态变量。
回调时,新任务可以不管旧任务的事情;
通知时,新任务必须间断地等待是否有通知,如果有通知,就处理它。等待的时候,新任务一般处于阻塞状态;
状态时,新任务不必进行等待操作,它只需要适时检测(判断)这个状态变量是否有效(即是否为有效值)就可以了,这种方法也就是轮询。
2.8 并发与并行
1 并发的含义
当有多个进程在运行时,如果系统是单核的CPU,那它根本不可能真正地同时运行一个以上的进程。系统只能把CPU运行时间划分成若干个时间段(在每个时刻段的起始时刻使用调度算法分配任务),再将每个时间段分配给每个进程执行。在一个时间段内,某进程在运行时,其它进程处于挂起状态(就绪状态)。这种方式我们称之为并发(Concurrent)。
首先,上述讲到的进程调度就涉及到了进程并发。并发的精髓就是分配时间片,微观上是间断的,宏观上是连续的。假如系统一共有26个进程,在一个时间段内,只运行进程A,接着在下一个时间段内运行进程B,直到运行完进程Z,那么所有进程都被运行过了。进程被“重视”的标志就是它的CPU时间,时间多了,运行的就久,进度就越快。当前A-Z的顺序只是一个例子,在真实情况中很少出现这种情况。
上面的定义中,提到了单核的概念。
单核是和多核相区分的,可以这么理解,某时刻,单核CPU只能做一个任务,而多核CPU可以做多个任务。任务做的越多,任务的进度就越快速,系统完成任务的效率就高了。
还有一个概念是超线程(Hyperthreading Technology)。
超线程技术就是通过采用特殊的硬件指令,可以把两个逻辑内核模拟成两个物理超线程芯片,在单处理器中实现线程级的并行计算,同时在相应的软硬件的支持下大幅度提高运行效能,从而实现在单处理器上模拟双处理器的效能。其实,从实质上说,超线程是一种可以将CPU内部暂时闲置处理资源充分“调动”起来的技术。
虽然采用超线程技术能够同时执行两个线程(如果每个进程同一时刻只能运行它的一个子线程的话,那就等同个能够同时执行两个进程),但它并不像两个真正的CPU那样,每个CPU都具有独立的资源。当两个线程都同时需要某一个资源时,其中一个要暂时停止,并让出资源,直到这些资源闲置后才能继续。因此超线程的性能并不等于两颗CPU的性能。
超线程与多核的区别主要取决于资源的独立性。当运行的这两个线程属于同一进程,那么对于超线程技术,就会遇到两个线程的资源发生冲突的情况;对于多核,就不会发生这种情况,因此两个线程在两个不同的CPU之中运行,纵使它们属于同一进程。
2 并行的含义
当系统有一个以上CPU(即多核)时,则线程的操作有可能不是并发的。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
并行是多核CPU的概念。并发是微观上间断,宏观上连续,而并行在微观上离“连续”更近了一步。
3 并发与并行的区别
并发与并行这两个概念很容易混淆。
并行是指两个或者多个事件在同一时刻发生;并发是指两个或多个事件在同一时间间隔内发生。
并发是单核CPU的产物,微观上间断,宏观上连续;并行是多核CPU的产物,微观上更连续,宏观上更连续。
以数硬币为例,总共一堆硬币。并发是一个人A数,并行是多个人B1-Bn数。
对A来说。选择一:从头到底埋头数;选择二:将硬币分成大致相同的N份,一会儿数这一份,一会儿数那一份。
对B来说。B将硬币分成大致相同的N份,因此B有N个人,所以这N个人分别数这N份硬币,由于人多力量大,所以B比A先数完。
A的选择一即为单道程序,选择二为多道程序即并发;B的选择即并行。
- 并行的程序比并发的程序效率高,资源利用率高,但编程更复杂,且结果不可预见,调试困难;
- 并行会有对资源的争夺,而并发不会(某时刻只有一个程序独占资源),因而并行会有互斥与同步问题,还有由此导致的死锁问题;
- 并发是单核CPU的产物,微观上间断,宏观上连续;并行是多核CPU的产物,微观上更连续,宏观上更连续。
2.9 死锁的基础概念
1 死锁的定义
死锁的规范定义:集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。
2 死锁发生的四个必要条件
- 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
- 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
- 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
- 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源,P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源
2.10 用户态和内核态
介绍:
用户态:只能受限地访问内存地址,且不允许访问外围设备,没有占用CPU地能力,CPU资源可以被其他程序获取
内核态:可以访问内存所有数据以及外围设备,也可以进行程序的切换
为什么要分:
安全性:防止用户程序恶意或者不小心破坏系统/内存/硬件资源
封装性:用户程序不需要实现更加底层地代码
利于调度:如果多个用户程序都在等待键盘输入,这时就需要进行调度;统一交给操作系统调度更加方便
如何从用户态切换到内核态:
系统调用:比如读取命令行输入,本质上是通过中断实现的
用户程序发生异常时:比如缺页异常
外围设备的中断:外围设备完成用户请求的操作之后,会向CPU发出中断信号,这时CPU会处理对应的中断处理程序
2.11 僵尸进程和孤儿进程
僵尸进程:
介绍:一个子进程结束后,但他的父进程并没有等待它,那么这个子进程将成为一个僵尸进程
特点:一个死亡的进程,但是并没有销毁,放弃了几乎所有的内存空间,没有任何可执行的代码,也不能被调度,仅仅在进程表中保留一个位置,记载该进程的ID,终止状态以及资源利用信息(CPU事件,内存使用量等等)供父进程手机
危害:占用进程号,系统所能使用的进程号是有限的,占用内存
孤儿进程:
介绍:一个父进程已经结束了,但是它的子进程还在进行,那么这些子进程将称为孤儿进程
孤儿进程会被init结果,当这些孤儿进程结束时由init完成状态收集工作
2.12 虚拟内存
介绍:每个进程拥有独立地地址空间,这个空间被分为大小相等的多个块,称为页。每个页都是一段连续的地址,这些页被映射到物理地址,但并不是所有页都必须在内存中才能运行程序。当程序运行引用到一部分在屋里内存中的地址空间时,由硬件进行必要的映射,当程序引用一部分不在屋里内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败命令
特点:对于进程而言,逻辑上似乎有很大的内存空间,实际上其中一部分对应物理内存上的一块(称为帧,通常页和帧的大小相等),还有一些没加载在内存中的对应在硬盘上。
页面置换算法:
FIFO先进先出算法:在操作系统中经常被用到,比如作业调度
LRU最近最少使用算法:根据使用时间到现在的长短来判断
LFU最少使用次数算法:根据使用次数来判断
OPT最优置换算法:理论的最优,保证置换出去的时不再被使用的页
虚拟内存的好处:
在内存中可以保留多个进程,系统并发度提高
解除了用户与内存之间的紧密约束,进程可以比内存的全部空间还大
2.13 分页和分段的区别
页式存储:一种用户视角内存与物理内存相分离的内存分配管理方案。将程序的逻辑地址划分为固定大小的页。而物理内存划分为同样大小的帧。没有外碎片,但会产生内碎片
段式存储:一种符合用户视角的内存分配管理方案,将程序的地址空间划分为若干段,如代码段,数据段,堆栈段,相互独立,互不干扰
区别:
目的不同:分页是由于系统管理的需要而不是用户的需要,他的信息是物理单位;分段的目的是为了能更好的满足用户的需要,他是信息的逻辑单位,它含有一组其意义相对完整的信息;
大小不同:页的大小由系统固定,而段的长度却不固定,由其所完成的功能决定
地址空间不同:段向用户提供二维地址空间,页面向用户提供一维地址空间
信息共享:段是信息的逻辑单位,便于存储保护和信息共享,页的保护和共享受限制
内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。