1.进程有哪些常见状态?各个状态之间的转换条件是什么?
1)就绪:进程处于准备好运行的状态,即进程已经分配到除CPU以外的所有必要资源后,只要获得CPU便可立即执行;
2)执行:进程已经获得CPU,程序处于正在执行的状态;
3)阻塞:正在执行中的进程由于发生了某时间(如IO请求,申请缓冲区失败等等)暂时无法继续执行的状态。
2.什么是上下文切换
对于单核单线程CPU而言,在某一时刻只能执行一条CPU指令。上下文切换(Context Switch)是一种将CPU资源从一个进程分配给另一个进程的机制。从用户角度看,计算机能够并行运行多个进程,这恰恰是操作系统通过快速上下文切换造成的结果。在切换的过程中,操作系统需要先存储当前进程的状态,包括内存空间的指针,当前执行完的指令等等,再读入下一个进程的状态,然后执行此进程。
3.进程与线程的区别与联系
名词释义:
进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程拥有独立的地址空间,一个进程无法直接访问另一个进程的变量和数据结构。
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,每个线程使用其所属进程的栈空间。同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时, 每个线程还拥有自己的寄存器和栈,其它线程可以读写这些栈内存。
3.1.进程与线程的关系
1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。
2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段。用来存放所有的局部变量和临时变量。
3)处理机分给线程,即真正再处理机上运行的是线程。
4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
3.2.进程与线程的区别
1)进程有自己的独立地址空间,线程没有。
2)进程是资源分配的最小单位,线程是CPU调用的最小单位。
3)进程和线程的通信方式不同,线程之间的通信比较方便,统一进程下的线程数据共享(比如全局变量,静态变量等等),通过这些数据来通信不仅快捷而且方便。当然,如何处理好这些访问的同步与互斥是多线程程序编写的难点。而进程之间的通信只能通过进程通信的方式进行。
4)进程上线文切换开销大,线程开销小。
5)一个进程挂掉了不会影响其他进程,而线程挂掉了有可能会影响其他线程(如果子线程的崩溃是由于自己的一亩三分地引起的,那就不会对主线程和其他子线程产生影响,但是如果子线程的崩溃是因为对共享区域造成了破坏,那么大家就一起崩溃了)。
6)对进程操作一般开销都比较大,线程开销就小很多。
3.3.为什么进程上下文切换比线程上下文切换的代价高
进程切换分为两步:
1)切换页目录以及使用新的地址空间;
2)切换内核栈和硬件上下文
对于Linux来说,线程和进程的最大区别就在于地址空间,对于线程切花是不需要做的,第2是进程和线程切换都是要做的。
切换的性能消耗:
1)线程上下文切换和进程上下文切换的一个最主要的区别是,线程切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
2)另一个隐藏的损耗是上下文切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有的已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(progressor's translation lookaside buffer,TLB)会被刷新,这将导致内存的访问再一段时间内相当低效,但是在线程切换中不会出现这个问题。
4.进程同步是什么?遵循什么原则?
进程同步的主要任务:
是对多个相关进程再执行次序上进行协调,以使并发执行的诸进程之间能够有效地共享资源和相互合作,从而使程序的执行具有可再现性。
同步机制遵循的原则:
1)空闲让进;
2)忙则等待(保证对临界区的互斥访问);
3)有限等待(有限代表时间有限,避免死等);
4)让权等待(当进程不能进入自己的临界区时,应该释放处理机,以免陷入忙等状态);
5.不同进程的通信方式有哪些?
进程通信指进程之间的信息交换(信息量少则一个状态或者数值,多则成千上万字节)。
对于限号量进行的进程间的互斥和同步,由于其所交换的信息量少而被归结为低级通信,例如kill。
所谓的高级进程通信指的是:用户可以利用操作系统所提供的一组通信命令传送大量数据的一种通信方式。操作系统隐藏了进程通信的实现细节,所以通信对用户来说是透明的。
高级通信机制可以归为三大类:
1)共享存储系统(存储器中划分的共享存储区),应用举例:
“剪切板”(剪切板实际上是系统维护管理的一块内存区域)的通信方式。ctrl+c复制完word中的内容,存储到剪切板中,ctrl+v读取剪切板中的数据,在ppt中粘贴,即完成了word和ppt进程间的通信;
2)消息传递系统(进程间的数据交换以message为单位,当今最流向的微内核操作系统中,微内核与服务器之间的通信,无一例额外地都采用了消息传递机制)。应用举例:
邮槽(MailSlot)是基于广播体系设计出来的,它采用无连接的不可靠数据传输。邮槽是以何种单向通信机制,创建邮槽的服务器进程读取数据,打开邮槽的客户机进程写入数据。
3)管道通信系统(连接读写进程以实现他们之间的通信的共享文件,类似先进先出的队列,又一个进程写,另一个进程读)。
管道有如下特质:
1.其本质是一个伪文件(实为内核缓冲区)
2.由两个文件描述符引用,一个表示读端,一个表示写端。
3.规定数据从管道的写端流入管道,从读端流出。
管道分为:匿名管道,命名管道。
匿名管道:是一个未命名的,单向管道,通过父进程和子进程之间传输数据,只能在本地机器上进行两个进程的通信。
命名管道:不仅可以在本机上实现两个进程的通信,还可以跨网络实现两个进程的通信。
6.进程调度的理解
6.1 调度的种类
高级调度:又称为作业调度,它决定把后背作业调入内存运行。
低级调度:又称为进程调度,它决定把就绪队列的某进程获得CPU。
中级调度:又称为再虚拟存储器中引入,在内存、外存对换区进行进程对换?
6.2 非抢占式调度和抢占式调度
非抢占式:分配程序一旦吧处理机分配给某进程后边一直运行下去,知道进程完成或者发生进程调度某事件而阻塞时,才把处理机分配给另一个进程。
抢占式:操作系统将正在运行的进程强行暂停,由调度程序将CPU分配给其他就绪进程的调度方式。
6.3 调度策略的设计
响应时间:从用户输入到产生反应的时间
周转时间:从任务开始到任务结束的时间
CPU任务可以分为交互式任务和批处理任务,调度的最终目标是合理的使用CPU,是得交互式任务的响应时间尽可能短,用户不至于感到延迟,同事使得批处理任务的周转时间尽可能短,减少用户的等待时间。
常用的调度算法以及特点:
1)FIFO或者FCFS(First Come,First Served,先来先爽)
·调度的顺序就是任务到达就绪队列的顺序;
·公平、简单、非抢占、不合适交互式;
·未考虑任务特性,平均等待时间可以缩短;
·比较有利于长作业,而不利于短作业
·有利于CPU繁忙型作业,而不利于I/O繁忙型作业
·用于批处理系统,不适于分时系统
2)Shortest Job First(SJF) 最短作业优先:
·SJF(CPU区间长度最小)最先调度,可以保证最小的平均等待时间
·对长作业不利,长作业容易出现"饥饿现象"
3)Shortest Remaining Job First(SRJF) 最短剩余作业优先:
·SJF的可抢占版本,这种方式可以使新的短作业获得良好的服务
4)优先权调度:
·每个任务管理一个优先权,调度优先权最高的任务。
·用户可以自定义优先权,但是会出现优先权太低的任务一直就绪,得不到运行,出现”饥饿“现象
5)Round-Robin(RR)轮转调度算法:
·设置一个时间片,按照时间片轮转调度;
·优点:定时有响应,等待时间较短;缺点:上下文切换次数较多
6)多级队列调度:
·按照一定的规则建立多个进程队列;
·不同的队列有固定的优先级;
·不同队列可以给不同的时间片和采用不同的调度方法;
·无法区分IO密集型和CPU密集型计算;也存在一定程度的”饥饿“现象。
7)多级反馈队列:
·在多级队列的基础上,任务可以在队列之间移动,更细致的区分任务;
·可以根据使用CPU时间多少来移动队列,阻止”饥饿”;
·最通用的调度算法,多数OS都是使用该方法或其变形,如UNIX、Windows等;
算法描述(百度百科):
1、进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。
2、首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。例如:Q1,Q2,Q3三个队列,当且仅当在Q1中没有进程等待时才去调度Q2,同理,只有Q1,Q2都为空时才会去调度Q3。
3、对于同一个队列中的各个进程,按照FCFS分配时间片调度。比如Q1队列的时间片为N,那么Q1中的作业在经历了N个时间片后若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列,直至完成。
4、在最后一个队列QN中的各个进程,按照时间片轮转分配时间片调度。
5、在低优先级的队列中的进程在运行时,又有新到达的作业,此时须立即把正在运行的进程放回当前队列的队尾,然后把处理机分给高优先级进程。换而言之,任何时刻,只有当第1~i-1队列全部为空时,才会去执行第i队列的进程(抢占式)。特别说明,当再度运行到当前队列的该进程时,仅分配上次还未完成的时间片,不再分配该队列对应的完整时间片。
7.死锁条件以及如何处理死锁问题
7.1 死锁定义:
如果一组进程中的每一个进程都在等待该组进程中的其他进程才能引发的时间,那么该组进程就是死锁的。或者在两个或多个并发进程中,每个进程持有某种资源而又都等待别的进程释放它或者它们现在保持着的资源,在为改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗地讲,就是两个或者多个进程被无限期地阻塞、互相等待的一种状态
7.2 死锁产生的必要条件:
1)互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用;
2)请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源;
3)非抢占条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺;
4)循环等待(Circular wait):系统中若干进程组成环路,该环路中的每个进程都在等待相邻的进程正占用的资源。
7.3 如何处理死锁问题:
1)忽略该问题,鸵鸟算法,可以应用在极少发生在死锁的情况下?
2)检测死锁并恢复;
3)仔细对资源进行动态分配,使系统始终处于安全状态以避免死锁;
4)破坏死锁的四个必要条件之一,防止死锁的产生;
8.说说你对临界资源的认识
1)在操作系统中,进程是占有资源的最小单位。线程可以访问其所在进程内的所有资源,但是线程本身并不占有资源或者说是仅仅占有一点必须的资源。但是对于某些资源来说,其在同一时间只能被一个进程所占用。这些一次只能被一个进程所占用的资源就是所谓的临界资源。典型的临界资源比如物理上的打印机,或者是存在硬盘/内存中的被多个进程所共享的一些变量和数据等。如果这类资源不被看成临界资源加以保护,那么很有可能造成数据丢失的问题。
2)对于临界资源的访问,必须是互斥进行。也就是说当临界资源被占用时,另一个申请临界资源进程会被阻塞,知道其所申请的临界资源被释放。而进程内访问临界资源的代码被称为临界区。
9.什么是虚拟内存,有什么优缺点
定义:具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。其逻辑容量由内存与外存之和决定。
与传统的存储器比较,虚拟内从主要有以下三个特征:
1)多次性,指无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行。
2)兑换性,指无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换入和换出。
3)虚拟性,指从逻辑上扩充内存的容量,使用户所看到的内存容量,远大于实际的内存容量。
虚拟内存的实现方式有两种:请求分页存储管理和请求分段存储管理。
10.页面兑换算法的理解
操作系统将内存按照页面进行管理,在需要的时候才把进程相应的部分调入内存。当产生缺页中断时,需要选择一个页面写入。如果要换出的页在内存中被修改过,变成了脏页,就需要先写到磁盘。页面置换算法,就是要选出最合适的一个页面,使得置换的效率最高。页面置换算法有很多,LRU是比较重要也是比较常用的算法。
最优页面置换算法思路:
最理想的情况下,我们给页面做个标记,挑选最远才会被再次用到的页面调出。当然,这样的算法是无法实现的,因为不确定一个页面在何时会被用到。
1)先进先出置换算法(FIFO):
这种算法的思想和队列是一样的,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。实现:把一个进程已调入内存的页面按先后次序链接成一个队列,并设置一个指针,使他总是指向最老的页面。对于一些经常被访问的页面如全局变量,函数,例程等页面,不能保证这些不被淘汰。
2)最近最少使用的页面置换算法(LRU):
根据页面调入内存后的使用情况作出决策。LRU置换算法是选择最近最久未使用的页面进行淘汰。
·为每个在内存中的页面配置一个移位寄存器。定时信号将每一隔一段时间将寄存器右移一位。最小数值的寄存器对应的页面就是最久未使用的页面。
·利用一个特殊的栈保存当前使用的各个页面的页面号。每当进程访问页面时,便将该页面的页面号从栈中移出,将它压如栈顶。因此,栈顶用用是最新未被访问的页面号,栈底是最近最久未被访问的页面号。
11.中断与系统调用的认识
所谓的中断就是计算机在执行程序的过程中,由于出现了某些特殊的事情,使得CPU暂停对程序的执行,转而去执行处理这一事件的程序。这些特殊事件处理完成之后再回去执行之前的程序。
中断一般分为三类:
1)由计算机硬件异常或故障引起的中断,称为内部异常中断;
2)由程序中执行了引起中断的指令而造成的中断,称为软中断(这也是和我们将要说明的系统调用相关的中断);
3)由外部设备请求引起的中断,称为外部中断。简单来说,对中断的理解就是对一些特殊事情的处理。
与中断紧密相连的一个概念就是中断处理程序了。当中断发生的时候,系统需要去对中断进行处理,对这些中断的处理是由操作系统内核中的特定函数进行的,这些处理中断的特定的函数就是我们所说的中断处理程序了。
另一个与中断紧密相连的概念就是中断的优先级。中断的优先级说明的是当一个中断正在被处理的时候,处理器能接受的中断的级别。中断的优先级也表明了中断需要被处理的紧急程度。每个中断都有一个对应的优先级,当处理器在处理某一中断的时候,只有比这个中断优先级高的中断可以被处理器接受并且被处理。优先级比这个当前正在被处理的中断优先级要低的中断将会被忽略。
典型的中断优先级如下所示:机器错误 > 时钟 > 磁盘 > 网络设备 > 终端 > 软件中断
进程的执行在系统上的两个级别:用户级和核心级,也称为用户态和系统态(user mode and kernel mode)。
用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。用户进程和系统进程的所有数据都在内存中。处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。
用户态切换到内核态的方式如下:
系统调用:程序的执行一般是在用户态下执行的,但当程序需要使用操作系统提供的服务时,比如说打开某一设备、创建文件、读写文件(这些均属于系统调用)等,就需要向操作系统发出调用服务的请求,这就是系统调用。
异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
用户态和核心态之间,最大的区别在于权限:
用户态的进程能存取它们自己的指令和数据,但不能存取内核指令和数据(或其他进程的指令和数据);
核心态下的进程能够存取内核和用户地址某些机器指令是特权指令,在用户态下执行特权指令会引起错误。在系统中内核并不是作为一个与用户进程平行的估计的进程的集合;
12.物理地址,逻辑地址,虚拟地址的区别
物理地址,内存真正的地址;
所谓的逻辑地址,是指计算机用户(例如程序开发者),看到的地址。例如,当创建一个长度为100的整型数组时,操作系统返回一个逻辑上的连续空间:指针指向数组第一个元素的内存地址。由于整型元素的大小为4个字节,故第二个元素的地址时起始地址加4,以此类推。事实上,逻辑地址并不一定是元素存储的真实地址,即数组元素的物理地址(在内存条中所处的位置),并非是连续的,只是操作系统通过地址映射,将逻辑地址映射成连续的,这样更符合人们的直观思维。
虚拟内存。操作系统读写内存的速度可以比读写磁盘的速度快几个量级。但是,内存价格也相对较高,不能大规模扩展。于是,操作系统可以通过将部分不太常用的数据移出内存,存放到价格相对较低的磁盘缓存,以实现内存扩展。操作系统还可以通过算法预测哪部分存储到磁盘缓存的数据需要进行读写,提前把这部分数据读回内存。虚拟内存空间相对磁盘而言要小很多,因此,即使搜索虚拟内存空间也比直接搜索磁盘要快
13.内部碎片与外部碎片
在内存管理中,内部碎片是已经被分配出去的的内存空间大于请求所需的内存空间。
外部碎片是指还没有分配出去,但是由于太小而无法分配给申请空间的新进程的内存空间空闲块。
14.守护、僵尸、孤儿进程的概念
守护进程:运行在后台的一种特殊进程,独立于控制终端并周期性地执行某些任务。
僵尸进程:一个进程 fork 子进程,子进程退出,而父进程没有wait/waitpid子进程,那么子进程的进程描述符仍保存在系统中,这样的进程称为僵尸进程。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,这些子进程称为孤儿进程。(孤儿进程将由 init 进程收养并对它们完成状态收集工作)。
15.什么是线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。