进程与线程面试题(亲身经历)

进程与线程是什么?以及它们的区别

答:

我们先说一下进程:

在早期未引入进程的OS中

例如多机处理系统中,并发执行程序的话(由于并发程序的速度不同与资源竞争导致其执行程序的间断),其会造成数据的不可再现,这样的程序失去其意义。

后来呢为了使得程序能并发执行且有效地对并发程序进行控制与描述,引入了进程的概念。

引入进程的OS:
程序在运行前,系统为之分配一个PCB(进程控制块:系统通过PCB对进程控制与描述),与程序段和程序相关的数据一起构成了进程实体。
而进程的实质就是指进程实体的一次运行过程。且它是资源分配和调度的基本单位。

我们来说一下线程:

进程呢,是一个资源的拥有者,因而在创建,销毁,切换进程时,系统付出的时空开销都很大,因此系统的进程数量不宜多,这限制了并发程度的提高。

后来呢,为了让更多程序更好的并发执行且尽量减少系统的开销,不少OS的学者想到将进程的两个属性分开,
由OS分开处理,(轻装上阵:对可调度和分派的基本单位,不作为拥有资源的单位) 和 (拥有资源的基本单位,又不对之进行频繁的切换),这种思路导致了线程的出现。

扫描二维码关注公众号,回复: 11593983 查看本文章

引入了线程的OS:

一个进程至少有一个线程:

线程作为一个可调度和分派的基本单位(利用CPU的基本单位),其几乎不拥有资源(必要的TCB),对其创建,销毁,切换开销十分小,且易于调度,进而提升了系统并发程度,且有利于发挥多处理器的功能。

进程作为系统资源分配的单位,为其多个线程提供资源,其已经不能作为可执行的实体,我们看到的执行的进程其实执行的是一个主线程。

我们从进程与线程的 调度,并发,拥有资源 和 系统开销 来对其进行区分和比较:

调度:

  • 在同一进程内,线程的切换不会引起进程的切换,但从一个进程的线程切换到另一个进程中的线程时,会引起进程的切换。

并发性:

  • 进程可并发执行, 且一个进程中多个线程之间也可并发执行,使得OS有更好的并发性,更加有效地提升系统资源的利用率和系统的吞吐量。

拥有资源:

  • OS 的进程可以拥有资源,是系统拥有资源的一个基本单位
  • 线程自己不拥有资源(每个线程都有一个用于控制线程运行的线程控制块TCB,用于指示被执行指令序列的程序计数器,保留局部变量,少数状态参数和返回地址等的一组寄存器和堆栈),但它可以访问隶属于进程的资源(进程的代码段,数据段及所拥有的系统资源。

系统开销:

  • 创建与销毁进程时,系统为之创建和回收进程控制块PCB,分配或回收其资源(内存空间,I/O设备),OS 为之付出的开销明显大于线程创建或撤销时的开销。

  • 进程切换时,涉及到当前进程CPU环境的保存及被新调度运行进程的CPU环境的设置,而线程的切换仅保存和设置少量寄存器内容,不涉及存储器管理方面的操作,这样看来,切换代价方面进程也是远高于线程的。

  • 同步与通信方面,一个进程中的多个线程具有相同的地址空间,在同步和通信的实现方面线程也比进程容易(且大多OS线程的切换同步与通信都无须OS内核的干预)

进程有哪几种状态?

  • 创建状态:系统分配给进程PCB,但进程还未进入到主存,创建工作还未完成还不能被调度运行。
  • 就绪状态:进程已经分配给其除了CPU之外的所有资源,这时进程在排队等待CPU的分配。
  • 执行状态:进程已经获取到CPU,并在运行。
  • 挂起状态 :在一些情况下会将该进程挂起(主动命令检查错误,OS需要时)
  • 阻塞状态:正在执行的进程遇到了某些事情而无法继续执行,这时会放弃处理器处于等待状态。
  • 终止状态:进程自然结束或是出现错误,或被OS终结都将进入终止状态,进入终止状态的进程不能再次执行,这时操作系统会
    去调用其他进程收集并保存其记录(状态码和计时统计数据),完毕后OS会删除该进程。

进程同步的机制

进程同步主要任务:对多个相关进程在执行次序上进行协调,以使并发执行的诸程序之间能有效地共享资源和相互合作,从而使程序执行具有再现性

信号量机制:作为其进程间与进程间不同线程间同步与互斥的主要手段,信号量用于表示资源数目的整型量 S,仅通过两个标准的原子操作(Atomic Operator)wait(S)和signal(S)来访问

管程机制:基于信号量的 抽象数据结构,里面定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据。

进程间的通信的几种方式及其作用原理

低级通信(可传送消息少):

  • 信号量(semaphore):作为其进程间与进程间不同线程间同步与互斥的主要手段,信号量用于表示资源数目的整型量 S,仅通过两个标准的原子操作(Atomic Operator)wait(S)和signal(S)来访问

  • 管程: 基于信号量的 抽象数据结构。

高级通信(可传送消息量多):

  • 共享存储器通信:相互通信的进程共享某些数据结构或共享存储区,进程间能通过这些空间通信
  • 消息传递通信:使用最广泛的进程通信方式,利用OS 提供的一组通信命令(原语),可以实现其大量数据的传递,且隐藏通信的实现细节(利用了共享信箱)。目前最广泛的消息传递通信方式是消息缓冲队列通信机制(通过缓冲区挂载在接收方进程的PCB的消息队列上实现)。
  • 管道通信机制:管道(发送进程与接收进程的共享文件)发送进程与读取进程都在一个文件中通信。

进程调度策略有哪几种?

  • 先来先服务调度算法FCFS:队列实现,非抢占,先请求CPU的进程先分配到CPU,可以作为作业调度算法也可以作为进程调度算法;按作业或者进程到达的先后顺序依次调度,对于长作业比较有利;

  • 最短作业优先调度算法SJF:作业调度算法,算法从就绪队列中选择估计时间最短的作业进行处理,直到得出结果或者无法继续执行,平均等待时间最短,但难以知道下一个CPU区间长度;缺点:不利于长作业;未考虑作业的重要性;运行时间是预估的,并不靠谱 ;

  • 优先级调度算法(可以是抢占的,也可以是非抢占的):优先级越高越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或饥饿;

  • 时间片轮转调度算法(可抢占的):按到达的先后对进程放入队列中,然后给队首进程分配CPU时间片,时间片用完之后计时器发出中断,暂停当前进程并将其放到队列尾部,循环 ;队列中没有进程被分配超过一个时间片的CPU时间,除非它是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么该进程就被抢占并放回就绪队列。

  • 高相应比算法HRN:响应比=(等待时间+要求服务时间)/要求服务时间;

  • 多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己的调度算法,队列之间采用固定优先级抢占调度。其中,一个进程根据自身属性被永久地分配到一个队列中。

  • 多级反馈队列调度算法:目前公认较好的调度算法;设置多个就绪队列并为每个队列设置不同的优先级,第一个队列优先级最高,其余依次递减。优先级越高的队列分配的时间片越短,进程到达之后按FCFS放入第一个队列,如果调度执行后没有完成,那么放到第二个队列尾部等待调度,如果第二次调度仍然没有完成,放入第三队列尾部…。只有当前一个队列为空的时候才会去调度下一个队列的进程。与多级队列调度算法相比,其允许进程在队列之间移动:若进程使用过多CPU时间,那么它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列,以防止饥饿发生。

线程同步的方式

线程间的并发同样需要同步机制来协调运行,保证其结果的正确性。

  • 互斥锁(mutex):用于实现线程间对资源互斥访问的机制, 将临界资源上锁,保证其临界资源仅有一个线程访问,线程访问结束,开启互斥锁(unlock)。
  • 条件变量(condition_variable): 条件变量是为了解决线程死锁问题的,与互斥锁搭配使用,它会将等待线程长时间阻塞,并将其搭配的互斥锁解锁,直到所等待的资源获取后恢复其原始状态。
  • 信号量机制:实现线程间对资源的同时访问机制,设置其信号量大小,控制其线程访问的个数。

用户态和核心态的区别。

  • 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。

  • 每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

用户态切换到内核态的3种方式:系统调用、异常、外围设备中断。

线程的实现方式?用户级线程与内核支持线程的区别?

根据OS内核是否对其线程感知,可以分为用户级线程与内核支持线程。

内核支持线程(KST):内核空间为每一个内核支持线程设置了线程控制块(其TCB保存在内核中),内核根据该控制块感知到某个线程的存在,并对其加以控制。

用户级线程ULT(User Level Threads)仅存在于用户空间中,无须系统调用来实现其功能,也无需内核的支持。

区别 :

线程管理方面:内核支持线程是由内核进行管理的,而用户级线程是由所在进程管理。
线程切换方面:用户级线程切换不需要进入内核空间,节省了模式切换开销和内核宝贵资源,而内核支持线程在内核支持下切换,其因具有非常轻量的数据结构,其切换非常快,开销也很小。
阻塞处理方面:当内核支持线程进行系统调用阻塞了,内核可调度进程的其他线程占有处理器运行,但在用户级线程在系统调用时被阻塞了,(大多数系统调用都会阻塞其用户进程)代表了其进程被阻塞了,进程内的所有线程都会被阻塞,

但在执行用户的线程切换时,其切换代价大,需要从用户态转换到内核态进行,代价很大。

猜你喜欢

转载自blog.csdn.net/chongzi_daima/article/details/107354393