问题一、操作系统的基本特性1、并发性并发性是指能够在一段时间内同时运行多个程序,并行指能够同时运行多个程序的指令。操作系统通过引入进程和线程使程序能够并发运行。2.共享共享是指系统中的资源可以被多个并发进程共享。它主要有两种分享方式:独占分享和同时分享。当多个应用程序并发执行时,需要在宏观上体现它们同时访问资源,在微观上实现它们的互斥访问。比如我们提到的内存。3、虚拟技术将一个物理实体转化为多个逻辑实体。采用多道程序技术(程序交替运行),让每一位用户都觉得有一台电脑是专属于他的。虚拟技术主要有两种:时间复用技术和空间复用技术。时间复用技术是指多个进程可以在同一个处理器上并发执行,让每个进程轮流占用处理器,每次只执行一个小的时间片,快速切换。空分复用技术将物理内存抽象成一个地址空间,每个进程都有自己的地址空间。当需要地址空间时,如果不需要则执行页面替换算法。4.异步异步是指进程不是一次性执行,而是停止又开始,以未知的速度向前推进。但只要运行环境相同,OS就需要保证程序运行的结果也相同。问题二、进程和线程的本质区别,以及各自的使用场景(重要)1、进程进程是资源分配的基本单位。这就像手机上的应用程序。2、线程线程是独立调度的基本单元。一个进程中可以有多个线程,它们共享进程资源。3.进程和线程的理解QQ和浏览器是两个进程。浏览器进程中有很多线程,比如HTTP请求线程、事件响应线程、渲染线程等,线程的并发执行使得在浏览器中点击一个新的线程链接发起HTTP请求时,浏览器也可以响应到用户的其他事件。4、进程与线程的区别(1)资源分配进程是资源分配的基本单位,但线程不拥有资源,多个线程可以共享进程资源。(2)资源调度在同一个进程中,线程切换不会引起进程切换。当从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。就像打开QQ再打开浏览器一样。(3)系统开销线程不占用系统资源,比进程开销效率更高。这是因为当一个进程被创建或撤销时,系统必须为其分配或回收资源,如内存空间、I/O设备等,并且在切换进程时,CPU状态也必须被保存。(4)对于一些需要同时共享某些变量的并发操作,只能使用多线程,不能使用多进程。问题三:进程的几种状态进程主要是三种状态。(1)准备好了。该进程已获取除CPU之外的所有所需资源,正在等待分配CPU资源(2)以运行。已获取CPU资源,正在运行。处于运行状态的进程数<=CPU核数(3)被阻塞。进程等待某些条件,直到满足条件才能执行。这里最重要的是状态之间的切换。例如,阻塞状态无法到达运行状态。问题四:常见的进程同步方式和线程同步方式1、进程同步方式(1)为什么需要进程同步?多进程虽然提高了系统资源利用率和吞吐量,但是进程的异步可能会造成系统混乱。进程同步的任务是协调多个相关进程的执行顺序,使多个并发执行的进程能够有效共享资源,相互协作,保证程序执行的可重现性。(2)同步机制要遵循的原则:Idlelet-in:当临界区内没有进程时,应允许其他进程申请进入临界区。忙等待:如果当前有进程在临界区,如果有其他进程申请进入,则必须等待,以保证互斥访问临界区。有限等待:对于需要访问临界资源的进程,需要在限定时间内打嗝进入临界区,防止死等待。等待:当进程无法进入临界区时,需要释放处理器,趁其忙等待。(3)进程同步方式:原子操作、信号量、监视器。2、线程同步方式(1)互斥(信号量)数量,每一时刻只有一个线程可以访问公共资源。只有具有互斥对象的线程才能访问公共资源。mutex对象只有一个,一次只能有一个线程持有,这样就保证了公共资源不会被多个线程同时访问。(2)信号量,允许多个线程同时访问公共资源。控制当时访问资源的最大线程数。(3)windows中的事件(linux中的条件变量)。通过通知的方式来保持多线程的同步,也可以轻松实现多线程优先级的比较(4)临界区。在任何时候,只有一个线程可以进入临界区并访问临界资源。问题5.windows和linux进程间的通信方式不同。问题6.进程任务调度算法的特点及使用场景(1)时间片轮询调度算法(RR):给每个进程一个固定的执行时间,让进程按照顺序在单位时间片内执行其中进程到达,执行完成后,调度下一个进程执行。时间片轮转调度不考虑进程等待时间和执行时间,属于抢占式调度。优点是兼顾了长作业和短作业;缺点是平均等待时间较长,上下文切换比较耗时。适用于分时系统。(2)先来先服务调度算法(FCFS):按照进程到达的顺序执行进程,不管等待时间和执行时间,会发生饥饿。属于非抢占式调度。优点是公平,实施简单;缺点是不利于短工。(3)优先级调度算法(HPF):选择进程等待队列中优先级最高的一个执行。(4)多级反馈队列调度算法:结合时间片轮换和优先级调度,将进程按优先级划分到不同的队列中,先按优先级调度,如果优先级相同则按时间片轮换。优点是兼顾多空操作,响应时间好,可行性高,适用于各种操作环境。(5)高响应率优先调度算法:根据公式“响应率=(进程执行时间+进程等待时间)/进程执行时间”得到的响应率进行调度。高响应率优先算法在等待时间相同的情况下,作业执行时间越短,响应率越高,优先满足段任务。同时响应比例会随着等待时间的增加而增加,优先级也会增加,可以避免饥饿现象。优点是兼顾了长作业和短作业,缺点是计算响应比代价大,适用于批处理系统。问题7.死锁的成因,必要条件,死锁处理,手写死锁代码,java如何解决死锁1.死锁的原因是在两个或多个并发进程中。如果每个进程都持有某个进程,直到状态发生改变,等待其他进程释放自己持有的资源,才能继续前进时,就会发生死锁。就好像对方手里拿着自己需要的资源,自己不释放一样。2.死锁的四个必要条件(1)互斥。一种资源一次只能被一个进程占用(2)request和hold。当一个进程因为请求资源而被阻塞时,它不会释放它持有的资源(3)非剥夺。没有办法在进程终止之前剥夺其对资源的所有权(4)循环等待。几个进程在最后连接起来,形成循环等待关系。3.死锁处理(1)防止死锁。销毁后满足三个条件之一即可(互斥是非共享设备的特性,不可更改):(2)死锁避免。避免死锁并不是采取一定的限制措施提前破坏死锁的必要条件,而是为了防止系统在动态分配资源避免死锁的过程中进入不安全状态,如银行家算法、系统安全状态、安全性算法.(3)死锁的检测和释放:解决资源分配图中的死锁。4.死锁代码(1)使用信号量实现生产者-消费者为了同步生产者和消费者的行为,需要记录缓冲区中的项数。可以使用信号量来计算数量。这里需要两个信号量:empty记录空缓冲区的个数,full记录满缓冲区的个数。其中,空信号量用于生产者进程。当空信号量不为0时,producer可以放item;完整的信号量用于消费者进程。当fullsemaphore不为0时,可以移除consumerItems。#defineN100typedefintsemaphore;semaphoremutex=1;semaphoreempty=N;semaphorefull=0;voidproducer(){while(TRUE){intitem=produce_item();down(&empty);down(&mutex);insert_item(item);up(&mutex);up(&full);}}voidconsumer(){while(TRUE){down(&full);down??(&mutex);initem=remove_item();consume_item(item);up(&mutex);up(&empty);}}(2)使用monitor实现producer-consumer//monitormonitorProducerConsumerconditionfull,empty;integercount:=0;conditionc;procedureinsert(item:integer);beginifcount=Nthenwait(full);insert_item(item);count:=count+1;ifcount=1thensignal(empty);end;functionremove:integer;beginifcount=0thenwait(empty);remove=remove_item;count:=count-1;ifcount=N-1thensignal(full);end;endmonitor;//producerClientprocedureproducerbeginwhiletruedobeginitem=produce_item;ProducerConsumer.insert(item);endend;//Consumer客户端procedureconsumerbeginwhiletruedobeginitem=ProducerConsumer.remove;consume_item(item);endend;(3)读写问题允许多个进程同时读取数据,但同时读写writeandwriteandwrite操作是不允许的。一个整型变量count记录了读写数据的进程数,一个互斥量count_mutex用于锁住count,一个互斥量data_mutex用于锁住读写数据。typedefintsemaphore;semaphorecount_mutex=1;semaphoredata_mutex=1;intcount=0;voidreader(){while(TRUE){down(&count_mutex);count++;if(count==1)down(&data_mutex);//第一个读者需要数据被锁定以防止写入进程访问up(&count_mutex);read();down??(&count_mutex);count--;if(count==0)up(&data_mutex);up(&count_mutex);}}voidwriter(){while(TRUE){down(&data_mutex);write();up(&data_mutex);}}(4)哲学家用餐问题五位哲学家围坐在一张圆桌旁,食物放在每位哲学家面前。哲学家的生活包括两种交替的活动:吃饭和思考。哲学家吃饭时,需要先拿起自己左右两边的两根筷子,而且一次只能拿一根筷子。下面是一个错误的解法,考虑到如果所有的哲学家都同时拿起左手的筷子,那么他们就不能拿起右手的筷子,造成死锁。#defineN5voidphilosopher(inti){while(TRUE){think();take(i);//拿起左边的筷子take((i+1)%N);//拿起右边的筷子eat();put(i);put((i+1)%N);}}为了防止死锁,可以设置两个条件:左右筷子必须同时拿起;只有当两个邻居都没有吃饭时才允许吃饭。#defineN5#defineLEFT(i+N-1)%N//左邻居#defineRIGHT(i+1)%N//右邻居#defineTHINKING0#defineHUNGRY1#defineEATING2typedefintsemaphore;intstate[N];//跟踪每个哲学家的状态信号量mutex=1;//临界区互斥信号量[N];//每个哲学家一个信号量voidphilosopher(inti){while(TRUE){think();take_two(i);eat();put_two(i);}}voidtake_two(inti){down(&mutex);state[i]=HUNGRY;test(i);up(&mutex);down??(&s[i]);}voidput_two(i){down(&mutex);state[i]=THINKING;test(LEFT);test(RIGHT);up(&mutex);}voidtest(i){//尝试拿起两根筷子if(state[i]==HUNGRY&&state[LEFT]!=EATING&&state[RIGHT]!=EATING){state[i]=EATING;up(&s[i]);}}问题8:两种线程实现方式的优缺点是什么?Question9.内存管理方式:segment,page,segmentpage。比较它们的区别操作系统中内存管理分为三种,段页和段页。1、为什么需要三种管理方式?由于连续的内存分配方式会导致内存利用率低和内存碎片,因此需要对这些离散的内存进行管理。介绍了三种内存管理方法。2.分页存储管理(1)基本的分页存储管理没有页面替换功能,所以需要将整个程序的所有页面加载到内存中才能运行。(2)需要一个页表来记录逻辑地址和实际存储地址的映射关系,从而实现页号到物理块号的映射。(3)由于页表也存放在内存中,所以内存数据需要两次内存访问(一次是从内存中访问页表,找到指定的物理块号,加上页中的偏移量得到actualphysicaladdress;第二次是根据第一次获取的物理地址访问内存取回数据)。(4)为了减少两次访问内存对效率的影响,在分页管理中引入了快速表。访问内存数据时,首先查询快表中的页码。如果在快表中,直接读取对应的物理块号;如果没有找到,则访问内存中的页表,从页表中获取物理地址,同时将页表中的映射表项添加到快速表中。(5)在某些计算机中,如果内存的逻辑地址很大,程序中就会有很多页表项,而页表在内存中是连续存放的,所以相应地,一个连续的大内存空间就是必需的。为了解决这个问题,可以采用二级页表或者多级页表的方法,其中外页表一次调入内存连续存储,内页表离散存储.相应的,访问内存页表时需要进行地址转换,访问逻辑地址对应的物理地址时也需要进行地址转换,读取一次数据总共需要3次内存访问。3、分段存储管理分页是为了提高内存利用率,分段是为了满足程序员在编写代码时的一些逻辑需求(如数据共享、数据保护、动态链接等)。(1)分段内存管理中,地址是二维的,一维是段号,一维是段内地址;(2)每个段的长度不同,每个段内部都是从0开始寻址。在段管理中,每个段分配的是连续的内存,而段是离散分配的,所以也存在逻辑地址和物理地址的映射关系,对应于段表机制。段表中的每一项记录了段在内存中的起始地址和段的长度。段表可以放在内存中,也可以放在寄存器中。(3)访问内存时,根据段号和段表项的长度计算出当前访问的段在段表中的位置,然后访问段表得到该段的物理地址。根据物理地址和段中的偏移量,可以得到需要访问的内存。由于也有两次内存访问,因此在段管理中也引入了关联寄存器。4.分段和分页的比较(1)页是信息的物理单位,是从系统内存利用的角度提出的离散分配机制;段是信息的逻辑单元,每个段包含一组具有完整含义的信息,是从用户的角度提出的一种内存管理机制(2)页的大小是固定的,由系统决定;段的大小不确定,由用户决定(3)页地址空间是一维的,而段地址空间是二维的5.段页存储方式首先将用户程序分成几个段,然后将每个段分成若干页,并为每个段分配一个段名。这样,在段页管理中,一个内存地址由三部分组成:段号、段内页号、页内地址。段页内存访问:系统中设置了一个段表寄存器,用于存放段表的起始地址和段表的长度。地址转换时,根据给定的段号(还需要将段号与寄存器中段表的长度进行比较,防止越界)和寄存器中段表的起始地址,对应的可以获取段的段表项,从段表项中获取段对应的页表起始地址,然后利用逻辑地址中段中的页码从中查找页表项页表,并利用页表项中的物理块地址和逻辑页中的地址拼接形成物理地址,最后通过访问物理地址得到需要的数据。由于访问一条数据需要3次内存访问,所以在段分页管理中也引入了缓存寄存器。问题十、虚拟内存的作用1、虚拟内存的含义?(1)由于每个进程的内存空间是一致且固定的,链接器可以在链接可执行文件时设置内存地址,而不用去管理这些数据最终的实际内存地址,这就是独立内存空间的好处(2)当不同的进程使用相同的代码时,比如库文件中的代码,物理内存中可以只存一份这样的代码,不同的进程只需要映射自己的虚拟内存来节省内存(3)当程序需要分配连续内存空间,只需要在虚拟内存空间中分配连续空间即可,无需实际物理内存。空间,碎片可以利用。二、虚拟内存和物理内存的关系Issue11.页面置换算法1.算法解释(1)Optimalreplacementalgorithm:理想置换算法。替换策略是替换当前页面中未来最长时间不会被访问的页面。(2)先进先出置换算法:每次淘汰最先转移的页面。(3)最长时间未使用算法LRU:每次淘汰最长时间未使用的页面。使用时间戳。(4)Clockalgorithmclock(algorithmNRUnotrecentlyused):在页面上设置一个accessbit,将page链接成一个循环队列,当page被访问时将accessbit设置为1。页面替换时,如果当前指针指向的页面访问为0,则替换,否则设置为0,循环直到遇到位为0的页面(5)改进的Clock算法:基于Clock算法在上部增加一个修改位,替换时根据访问位和修改位综合判断。先替换访问修改位为0的页面,再替换访问位为0修改位为1的页面。(6)LeastusedalgorithmLFU:设置寄存器记录页面访问次数,替换每次更换时当前访问次数最少的一个。LFU和LRU很相似,支持的硬件也一样,但区分两者的关键在于一个是基于时间的,一个是基于次数的。(7)PageBufferAlgorithmPBA:替换时,无论页面是否被修改,都不会替换到磁盘中,而是暂存在内存中的页面列表中。再次访问时,可以直接从这些页面访问。在没有磁盘IO的情况下从链表中移除。当链表中的修改次数达到一定数量后,依次进行磁盘操作。2、Java实现LRU算法publicclassLRU{publicstaticvoidmain(String[]args){String[]inputStr={"6","7","6","5","9","6","8","9","7","6","9","6"};//内存块intmemory=3;List
