操作系统(背诵版)
1. 进程和线程的区别?
- 调度:进程是资源管理的基本单位,线程是程序执行的基本单位。
- 切换:线程上下文切换比进程上下文切换要快得多。
- 拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源。
- 系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,I/O设备等,OS所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销。
为什么需要线程?
线程产生的原因:进程可以使多个程序能并发执行,以提高资源的利用率和系统的吞吐量;但是其具有一些缺点:
-
进程在同一时刻只能做一个任务,很多时候不能充分利用CPU资源。
-
进程在执行的过程中如果发生阻塞,整个进程就会挂起,即使进程中其它任务不依赖于等待的资源,进程仍会被阻塞。
引入线程就是为了解决以上进程的不足,线程具有以下的优点:
-
从资源上来讲,开辟一个线程所需要的资源要远小于一个进程。
-
从切换效率上来讲,运行于一个进程中的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需时间也远远小于进程间切换所需要的时间(这种时间的差异主要由于缓存的大量未命中导致)。
-
从通信机制上来讲,线程间方便的通信机制。对不同进程来说,它们具有独立的地址空间,要进行数据的传递只能通过进程间通信的方式进行。线程则不然,属于同一个进程的不同线程之间共享同一地址空间,所以一个线程的数据可以被其它线程感知,线程间可以直接读写进程数据段(如全局变量)来进行通信(需要一些同步措施)。
2. 协程与线程的区别?
- 线程和进程都是同步机制,而协程是异步机制。
- 线程是抢占式,而协程是非抢占式的。需要用户释放使用权切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
- 一个线程可以有多个协程,一个进程也可以有多个协程。
- 协程不被操作系统内核管理,而完全是由程序控制。线程是被分割的CPU资源,协程是组织好的代码流程,线程是协程的资源。但协程不会直接使用线程,协程直接利用的是执行器关联任意线程或线程池。
- 协程能保留上一次调用时的状态。
3. 并发和并行有什么区别?
并发就是在一段时间内,多个任务都会被处理;但在某一时刻,只有一个任务在执行。单核处理器可以做到并发。比如有两个进程A和B,A运行一个时间片之后,切换到B,B运行一个时间片之后又切换到A。因为切换速度足够快,所以宏观上表现为在一段时间内能同时运行多个程序。
并行就是在同一时刻,有多个任务在执行。这个需要多核处理器才能完成,在微观上就能同时执行多条指令,不同的程序被放到不同的处理器上运行,这个是物理上的多个进程同时进行。
4. 进程与线程的切换流程?
进程切换分两步:
1、切换页表以使用新的地址空间,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。
2、切换内核栈和硬件上下文。
对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2步是进程和线程切换都要做的。
因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
5. 为什么虚拟地址空间切换会比较耗时?
进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个Cache就是TLB(translation Lookaside Buffer,TLB本质上就是一个Cache,是用来加速页表查找的)。
由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,Cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。
6. 进程间通信方式有哪些?
-
管道:管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
管道可以分为两类:匿名管道和命名管道。匿名管道是单向的,只能在有亲缘关系的进程间通信;命名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
-
信号 : 信号是一种比较复杂的通信方式,信号可以在任何时候发给某一进程,而无需知道该进程的状态。
Linux系统中常用信号:
(1)SIGHUP:用户从终端注销,所有已启动进程都将收到该进程。系统缺省状态下对该信号的处理是终止进程。(2)SIGINT:程序终止信号。程序运行过程中,按Ctrl+C键将产生该信号。
(3)SIGQUIT:程序退出信号。程序运行过程中,按Ctrl+\键将产生该信号。
(4)SIGBUS和SIGSEGV:进程访问非法地址。
(5)SIGFPE:运算中出现致命错误,如除零操作、数据溢出等。
(6)SIGKILL:用户终止进程执行信号。shell下执行kill -9发送该信号。
(7)SIGTERM:结束进程信号。shell下执行kill 进程pid发送该信号。
(8)SIGALRM:定时器信号。
(9)SIGCLD:子进程退出信号。如果其父进程没有忽略该信号也没有处理该信号,则子进程退出后将形成僵尸进程。
-
信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
-
消息队列:消息队列是消息的链接表,包括Posix消息队列和System V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
-
共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
-
Socket:与其他通信机制不同的是,它可用于不同机器间的进程通信。
优缺点:
- 管道:速度慢,容量有限;
- Socket:任何进程间都能通讯,但速度慢;
- 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;
- 信号量:不能传递复杂消息,只能用来同步;
- 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。
7. 进程间同步的方式有哪些?
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
优点:保证在某一时刻只有一个线程能访问数据的简便办法。
缺点:虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。互斥量跟临界区很相似,比临界区复杂,互斥对象只有一个,只有拥有互斥对象的线程才具有访问资源的权限。
优点:使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
缺点:
- 互斥量是可以命名的,也就是说它可以跨越进程使用,所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。
- 通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号量对象可以说是一种资源计数器。
3、**信号量**:为控制一个具有有限数量用户资源而设计。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。互斥量是信号量的一种特殊情况,当信号量的最大资源数=1就是互斥量了。
优点:适用于对Socket(套接字)程序中线程的同步。
缺点:
- 信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点;
- 信号量机制功能强大,但使用时对信号量的操作分散, 而且难以控制,读写和维护都很困难,加重了程序员的编码负担;
- 核心操作P-V分散在各用户程序的代码中,不易控制和管理,一旦错误,后果严重,且不易发现和纠正。
4、事件: 用来通知线程有一些事件已发生,从而启动后继任务的开始。
优点:事件对象通过通知操作的方式来保持线程的同步,并且可以实现不同进程中的线程同步操作。
8.进程的状态与状态转换
进程在运行时有三种基本状态:就绪态、运行态和阻塞态。
-
运行(running)态:进程占有处理器正在运行的状态。进程已获得CPU,其程序正在执行。在单处理机系统中,只有一个进程处于执行状态;在多处理机系统中,则有多个进程处于执行状态。
2.就绪(ready)态:进程具备运行条件,等待系统分配处理器以便运行的状态。 当进程已分配到除CPU以外的所有必要资源后,只要再获得CPU,便可立即执行,进程这时的状态称为就绪状态。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
3.阻塞(wait)态:又称等待态或睡眠态,指进程不具备运行条件,正在等待某个时间完成的状态。
各状态之间的转换:
-
就绪→执行 处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程便由就绪状态转变成执行状态。
-
执行→就绪 处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从执行状态转变成就绪状态。
-
执行→阻塞 正在执行的进程因等待某种事件发生而无法继续执行时,便从执行状态变成阻塞状态。
-
阻塞→就绪 处于阻塞状态的进程,若其等待的事件已经发生,于是进程由阻塞状态转变为就绪状态。
9.线程同步的方式有哪些?
1、临界区:当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止,以此达到用原子方式操 作共享资源的目的。
2、事件:事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
3、互斥量:互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,但是更节省资源,更有效率。
4、信号量:当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。
区别:
- 互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说互斥量可以跨越进程使用,但创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量 。因为互斥量是跨进程的互斥量一旦被创建,就可以通过名字打开它。
- 互斥量,信号量,事件都可以被跨越进程使用来进行同步数据操作。
10.进程调度策略有哪几种?
-
先来先服务:非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。另外,对I/O密集型进程也不利,因为这种进程每次进行I/O操作之后又得重新排队。
-
短作业优先:非抢占式的调度算法,按估计运行时间最短的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
-
最短剩余时间优先:最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
-
时间片轮转:将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
时间片轮转算法的效率和时间片的大小有很大关系:因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。 而如果时间片过长,那么实时性就不能得到保证。
-
优先级调度:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
11.常⻅的⼏种内存管理机制
1. 块式管理 : 远古时代的计算机操系统的内存管理⽅式。将内存分为⼏个固定⼤⼩的块,每个块中只包含⼀个进程。如果程序运⾏需要内存的话,操作系统就分配给它⼀块,如果程序运⾏只需要很⼩的空间的话,分配的这块内存很⼤⼀部分⼏乎被浪费了。这些在每个块中未被利⽤的空间,我们称之为碎⽚。
2. ⻚式管理 :把主存分为⼤⼩相等且固定的⼀⻚⼀⻚的形式,⻚面⼩,相对相⽐于块式管理的划分⼒度更⼤,提⾼了内存利⽤率,减少了碎⽚。⻚式管理通过⻚表对应逻辑地址和物理地
址。
3. 段式管理 : ⻚式管理虽然提⾼了内存利⽤率,但是⻚式管理其中的⻚实际并⽆任何实际意义。 段式管理把主存分为⼀段段的,每⼀段的空间⼜要⽐⼀⻚的空间⼩很多 。但是,最重要的是段是有实际意义的,每个段定义了⼀组逻辑信息,例如,有主程序段 MAIN、⼦程序段X、数据段 D 及栈段 S 等。 段式管理通过段表对应逻辑地址和物理地址。
4.段⻚式管理机制 。段⻚式管理机制结合了段式管理和⻚式管理的优点。简单来说段⻚式管理机制就是把主存先分成若⼲段,每个段⼜分成若⼲⻚,也就是说 段⻚式管理机制 中段与段之间以及段的内部的都是离散的。
12.什么是死锁?其条件是什么?怎样避免死锁?**
死锁的概念:在两个或多个并发进程中,如果每个进程持有某种资源而又都等待别的进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗地讲,就是两个或多个进程被无限期地阻塞、相互等待的一种状态。
死锁产生的原因主要是: 系统资源不足; 进程推进顺序非法。
产生死锁的必要条件:
(1)互斥(mutualexclusion),一个资源每次只能被一个进程使用;
(2)不可抢占(nopreemption),进程已获得的资源,在未使用完之前,不能强行剥夺;
(3)占有并等待(hold andwait),一个进程因请求资源而阻塞时,对已获得的资源保持不放;
(4)环形等待(circularwait),若干进程之间形成一种首尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
死锁的解除与预防:理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
死锁的处理策略:鸵鸟策略、预防策略、避免策略、检测与恢复策略。
13.孤儿进程,僵尸进程,守护进程
-
孤儿进程:如果父进程先退出,子进程还没退出那么子进程将被托孤给init进程,这是子进程的父进程就是init进程(1号进程).其实还是很好理解的
-
僵尸进程**:如果我们了解过linux进程状态及转换关系,我们应该知道进程这么多状态中有一种状态是僵死状态,就是进程终止后进入僵死状态(zombie),等待告知父进程自己终止,后才能完全消失.但是如果一个进程已经终止了,但是其父进程还没有获取其状态,那么这个进程就称之为僵尸进程.僵尸进程还会消耗一定的系统资源,并且还保留一些概要信息供父进程查询子进程的状态可以提供父进程想要的信息.一旦父进程得到想要的信息,僵尸进程就会结束.
-
守护进程***:守护进程就是在后台运行,不与任何终端关联的进程,通常情况下守护进程在系统启动时就在运行,它们以root用户或者其他特殊用户(apache和postfix)运行,并能处理一些系统级的任务.习惯上守护进程的名字通常以d结尾(sshd),但这些不是必须的.
**
14.什么是虚拟内存?
- 虚拟内存就是说,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,并且就叫做虚拟内存。
15.什么是临界区?如何解决冲突?
每个进程中访问临界资源的那段程序称为临界区,每次只准许一个进程进入临界区,进入后不允许其他进程进入。
(1)如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入;
(2)任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待;
(3)进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区;
(4)如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
16.局部性原理
局部性原理表现在以下两个方面:
- 时间局部性 :如果程序中的某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久以后该数据可能再次被访问。产生时间局部性的典型原因,是由于在程序中存在着大量的循环操作。
- 空间局部性 :一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定的范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式簇聚存储的。
17.什么是用户态和内核态
用户态和内核态是操作系统的两种运行状态。
- 内核态:处于内核态的 CPU 可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且占用 CPU 不会发生抢占情况,一般处于特权级 0 的状态我们称之为内核态。
- 用户态:处于用户态的 CPU 只能受限的访问内存,并且不允许访问外围设备,用户态下的 CPU 不允许独占,也就是说 CPU 能够被其他程序获取。
18.什么是内核
在计算机中,内核是一个计算机程序,它是操作系统的核心,可以控制操作系统中所有的内容。内核通常是在 boot loader 装载程序之前加载的第一个程序。
19.逻辑地址/物理地址/虚拟内存
-
逻辑地址,是指计算机用户(例如程序开发者),看到的地址。例如,当创建一个长度为100的整型数组时,操作系统返回一个逻辑上的连续空间:指针指向数组第一个元素的内存地址。由于整型元素的大小为4个字节,故第二个元素的地址时起始地址加4,以此类推。事实上,逻辑地址并不一定是元素存储的真实地址,即数组元素的物理地址(在内存条中所处的位置),并非是连续的,只是操作系统通过地址映射,将逻辑地址映射成连续的,这样更符合人们的直观思维。
-
虚拟内存。操作系统读写内存的速度可以比读写磁盘的速度快几个量级。但是,内存价格也相对较高,不能大规模扩展。于是,操作系统可以通过将部分不太常用的数据移出内存,“存放到价格相对较低的磁盘缓存,以实现内存扩展。操作系统还可以通过算法预测哪部分存储到磁盘缓存的数据需要进行读写,提前把这部分数据读回内存。虚拟内存空间相对磁盘而言要小很多,因此,即使搜索虚拟内存空间也比直接搜索磁盘要快。唯一慢于磁盘的可能是,内存、虚拟内存中都没有所需要的数据,最终还需要从硬盘中直接读取。这就是为什么内存和虚拟内存中需要存储会被重复读写的数据,否则就失去了缓存的意义。
-
物理地址指的是真实物理内存中地址,更具体一点来说就是内存地址寄存器中的地址。物理地址是内存单元真正的地址。
-
现代计算机中有一个专门的转译缓冲区(Translation Lookaside Buffer,TLB),用来实现虚拟地址到物理地址的快速转换。
与内存/虚拟内存相关的还有如下两个概念:
- 1) Resident Set
当一个进程在运行的时候,操作系统不会一次性加载进程的所有数据到内存,只会加载一部分正在用,以及预期要用的数据。其他数据可能存储在虚拟内存,交换区和硬盘文件系统上。被加载到内存的部分就是resident set。
- 2) Thrashing
由于resident set包含预期要用的数据,理想情况下,进程运行过程中用到的数据都会逐步加载进resident set。但事实往往并非如此:每当需要的内存页面(page)不在resident set中时,操作系统必须从虚拟内存或硬盘中读数据,这个过程被称为内存页面错误(page faults)。当操作系统需要花费大量时间去处理页面错误的情况就是thrashing。
20.IO多路复用
基本概念
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:
- 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。
- 当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。
- 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
- 如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。
- 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。
下面是一些在别的博客上看到的一些资料转载一下
*
*
*
*
*
*
*
*
*
*
*
*
*
*