高效面试之操作系统常考题

一:操作系统

1. 进程的有哪几种状态,状态转换图,及导致转换的事件。

2. 进程与线程的区别。

进程是 操作系统 资源分配 的单位,线程是 操作系统 执行 的单位,进程 有独立的地址空间 ,一个进程崩溃后,在保护模式下 不会对其它进程产生影响 ,而 线程只是一个进程中的不同执行路径 。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉 ,所以多进程的程序要比多线程的程序 健壮 ,但在 进程切换时,耗费资源较大,效率要差 一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

有了进程为什么还要线程?
在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了 CPU 的利用率 , 进程就是为了在CPU上实现多道编程而提出的 , 程还是有很多缺陷的,主要体现在两点上: 
1, 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。

2,进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的代码片,也将无法执行。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行

因为要并发,我们发明了进程,又进一步发明了线程 ,线程则属于在进程这个层次上再提供了一层并发的抽象
 进程与线程的区别

1)进程是操作系统资源分配的单位,线程是操作系统执行的单位。

2)进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮

3)线程是进程的一个实体CPU调度和分派的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源进程切换时,耗费资源较大,效率要差。所以,多线程比多进程要效率高

4)一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行

3. 进程通信的几种方式。

#   管道 ( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指 父子进程关系

命名管道  (named pipe) : 命名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

信号量 ( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作 为进程 间以及同一进程内不同线程之间的 同步手段

消息队列 ( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了 信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等 缺点。

信号  ( sinal ) : 信号是一种比较复杂的通信方式,用于 通知接收进程某个事件 已经发生。

共享内存 ( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是 最快的  IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

套接字 ( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

4. 线程同步几种方式。(一定要会写生产者、消费者问题,完全消化理解)

 
   
线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制。 
 1 临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
 2 互斥量:为协调共同对一个共享资源的单独访问而设计的。
 3 信号量:为控制一个具有有限数量用户资源而设计。
 4 事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 

 临界区效率高,但不是不可以跨进程使用。互斥量是可以命名的,也就是说它可以跨越进程使用,创建互斥量需要的资源更多,效率比临界区低信号量多个资源的多线程互斥问题 ,这与操作系统中的PV操作相同。它指出了同时访问共享 资源的线程 最大数目。更像一种资源计数器 ,mutex实际上是count=1情况下的semaphor

linux下有读写锁,适合读的次数远大于写的情况。

读写锁与互斥量类似,不过读写锁允许更高的并行性。互斥量要么是锁住状态要么是不加锁状态,而且一次只有一个线程可以对其加锁

 
      

5. 线程的实现方式. (也就是用户线程与内核线程的区别)

内核线程:   由操作系统内核创建和撤销。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。Windows   NT和2000/XP支持内核线程  

用户线程 :由应用进程利用 线程库创建和管理 ,不以来于操作系统核心。不需要用户态/核心态切换,速度快。操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。

6. 用户态和核心态的区别。

cpu的运行状态,特权级别最高的是ring 0,被视作核心态;级别最低的是ring 3,常被看作用户态;rings 1 and 2则很少被使用。用户态:Ring3运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中I/O许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。

核心态:Ring0 在处理器的存储保护中,核心态,或者特权态(与之相对应的是用户态), 是操作系统内核所运行的模式。运行在该模式的代码, 可以无限制地对 系统存储外部设备进行访问 

用户态切换到内核态的3种方式:
1) 系统调用:这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
2) 异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
3) 外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。 
当一个进程在执行时, CPU的所有寄存器中的值、 进程的状态以及 堆栈中的内容被称为该 进程的上下文
从用户态切换到核心态,要耗掉>100 cycle的CPU时钟
 

7. 用户栈和内核栈的区别。

内核创建进程,创建进程的同时创建进程控制块,创建进程自己的堆栈。一个进程有两个堆栈,用户栈和系统栈,用户堆栈的空间指向 用户地址空间,内核堆栈的空间指向 内核地址空间。

内核栈和用户栈区别

1.内核栈是系统运行在内核态的时候使用的栈,用户栈是系统运行在用户态时候使用的栈。

当进程由于中断进入内核态时,系统会把一些用户态的数据信息保存到内核栈中,当返回到用户态时,取出内核栈中得信息恢复出来,返回到程序原来执行的地方。
用户栈就是进程在用户空间时创建的栈,比如一般的函数调用,将会用到用户栈

2.内核栈是属于操作系统空间的一块固定区域,可以用于保存中断现场、保存操作系统子程序间相互调用的参数、返回值等。

用户栈是属于用户进程空间的一块区域,用户保存用户进程子程序间的相互调用的参数、返回值等。

3.每个Windows 都有4g的进程空间,系统栈使用进程空间的低段部分,用户栈是高端部分如果用户要直接访问系统栈部分,需要有特殊的方式。

为何要设置两个不同的栈?

共享原因:

内核的代码和数据是为所有的进程共享的,如果不为每一个进程设置对应的内核栈,那么就不能实现不同的进程执行不同的代码

安全原因:

如果只有一个栈,那么用户就可以修改栈内容来突破内核安全保护


8. 内存池、进程池、线程池。(c++程序员必须掌握)

理由:
1.线程执行过程分为三个过程,线程创建时间,线程执行时间,线程销毁时间。使用线程池不用频率摧毁和创建线程,减少了线程创建和销毁时间,提高效率。
2.预创建技术。
线程池的出现正是着眼于减少线程池本身带来的开销。线程池采用 预创建的技术,在应用程序启动之后,将 立即创建一定数量的线程(N1),放入 空闲队列中。这些线程都是处于 阻塞(Suspended)状态不消耗CPU,但占用较小的内存空间。当任务到来后,缓冲池选择一个空闲线程,把任务传入此线程中运行。
2.线程池实现
线程池管理器:用于创建并管理线程池
工作线程: 线程池中实际执行的线程
任务接口: 尽管线程池大多数情况下是用来支持网络服务器,但是我们将 线程执行的任务抽象出来,形成任务接口,从而使线程池与具体的任务无关。
任务队列:线程池的概念具体到实现则可能是队列,链表之类的数据结构,其中 保存执行线程
3.局限
线程池致力于减少线程本身的开销对应用所产生的影响,这是有前提的,前提就是 线程本身开销与线程执行任务相比不可忽略 。如果线程本身的开销相对于线程任务执行开销而言是可以忽略不计的,那么此时线程池所带来的好处是不明显的,比如对于 FTP服务器 以及Telnet服务器,通常传送文件的时间较长,开销较大,那么此时,我们采用线程池未必是理想的方法,我们可以选择“ 即时创建,即时销毁 ”的策略。
总之线程池通常适合下面的几个场合:
(1)  单位时间内处理 任务频繁而且任务 处理时间短
(2)  对 实时性要求较高。如果接受到任务后在创建线程,可能满足不了实时要求,因此必须采用线程池进行 预创建
(3)  必须经常面对 高突发性事件,比如 Web服务器,如果有足球转播,则服务器将产生巨大的冲击。此时如果采取传统方法,则必须不停的大量产生线程,销毁线程。此时采用动态线程池可以避免这种情况的发生

内存池:

内存池(memory pool)是代替直接调用malloc/free、new/delete进行内存管理的常用方法,当我们申请内存空间时,首先到我们的内存池中查找合适的内存块,而不是直接向操作系统申请,优势在于:

    1. 比 malloc/free进行内存申请/释放的方式快
    2.  不会产生或很少产生内存碎片
    3.  可避免内存泄漏
2.为什么内存池可以避免内存泄露?
其实说白了就是该内存空间使用完毕之后未回收,即所谓内存泄漏,我们通过 内存池 可以定义一个变量max_free_index , 设置允许的最大内存阀值 ,当超过改制后,释放内存,归还给操作系统

9. 死锁的概念,导致死锁的原因.

是指两个或两个以上的 进程在执行过程中,因 争夺资源而造成的一种 互相等待的现象,若 无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象:死锁。”

原因:

1.竞争资源引起进程死锁
当系统中供多个 进程共享的资源如 打印机、公用队列的等,其数目不足以满足诸进程的需要时,会引起诸进程对资源的竞争而产生死锁。
1 )可剥夺资源和不可剥夺资源
系统中的资源可以分为两类,一类是 可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺。例如,优先权高的 进程可以剥夺优先权低的进程的 处理机。又如,内存区可由 存储器管理 程序,把一个 进程从一个存储区移到另一个存储区,此即剥夺了该进程原来占有的存储区,甚至可将一进程从内存调到外存上,可见, CPU主存均属于可剥夺性资源。另一类资源是不可剥夺资源,当系统把这类资源分配给某 进程后,再不能强行收回,只能在进程用完后自行释放,如 磁带机打印机等。
2 )竞争不可剥夺资源
在系统中所配置的不可剥夺资源,由于它们的数量不能满足诸 进程运行的需要,会使 进程在运行过程中,因争夺这些资源而陷于僵局。例如,系统中只有一台 打印机R1和一台 磁带机R2,可供 进程P1和P2共享。假定PI已占用了 打印机R1,P2已占用了 磁带机R2,若P2继续要求打印机R1,P2将阻塞;P1若又要求磁带机,P1也将阻塞。于是,在P1和P2之间就形成了僵局,两个 进程都在等待对方释放自己所需要的资源,但是它们又都因不能继续获得自己所需要的资源而不能继续推进,从而也不能释放自己所占有的资源,以致进入死锁状态。
3 )竞争临时资源
上面所说的 打印机资源属于可顺序重复使用型资源,称为永久资源。还有一种所谓的临时资源,这是指由一个 进程产生,被另一个进程使用,短时间后便无用的资源,故也称为消耗性资源,如 硬件中断、信号、消息、 缓冲区内的消息等,它也可能引起死锁。例如,SI,S2,S3是临时性资源, 进程P1产生消息S1,又要求从P3接收消息S3;进程P3产生消息S3,又要求从进程P2处接收消息S2;进程P2产生消息S2,又要求从P1处接收产生的消息S1。如果消息通信按如下顺序进行:
P1: ···Relese(S1);Request(S3); ···
P2: ···Relese(S2);Request(S1); ···
P3: ···Relese(S3);Request(S2); ···
并不可能发生死锁。但若改成下述的运行顺序:
P1: ···Request(S3);Relese(S1);···
P2: ···Request(S1);Relese(S2); ···
P3: ···Request(S2);Relese(S3); ···
则可能发生死锁。
2.进程推进顺序不当引起死锁
由于 进程在运行中具有 异步性特征,这可能使P1和P2两个进程按下述两种顺序向前推进。
1)  进程推进顺序合法
进程P1和P2并发执行时,如果按照下述顺序推进:P1:Request(R1); P1:Request(R2); P1: Relese(R1);P1: Relese(R2); P2:Request(R2); P2:Request(R1); P2: Relese(R2);P2: Relese(R1);这两个进程便可顺利完成,这种不会引起 进程死锁的推进顺序是合法的。
2)  进程推进顺序非法
若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个 进程再向前推进,便可能发生死锁。例如, 当P1运行到P1:Request(R2)时, 将因R2已被P2占用而阻塞 ;当P2运行到P2:Request(R1)时, 也将因R1已被P1占用而阻塞 ,于是发生进程死锁

10. 导致死锁的四个必要条件。

死锁的发生必须具备以下四个必要条件
1) 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2) 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3) 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4) 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。


11. 处理死锁的四个方式。

1、 撤消陷于死锁的全部 进程
2、逐个撤消陷于死锁的 进程,直到死锁不存在;
3、从陷于死锁的 进程中逐个 强迫放弃所占用的资源,直至死锁消失。
4、从另外一些 进程那里 强行剥夺足够数量的资源分配给死锁进程,以解除死锁状态


12. 预防死锁的方法、避免死锁的方法。

采用资源静态分配,破坏“部分分配”条件

允许进程剥夺使用其他进程占用的资源,破坏“不可剥夺”条件

采用资源有序分配法,破坏“环路”条件

互斥条件无法破坏。


13. 进程调度算法。(周转时间 =  程序结束时间 — 开始服务时间、带权周转时间=  周转时间 /  要求服务时间)


14. Windows内存管理的方式(块式、页式、段式、段页式).

连续分配方式 会形成许多 内存碎片 ,虽可通过“紧凑”功能将碎片合并,但会付出很大开销。于是出现 离散分配方式

逻辑地址
程序产生的与 相关的 偏移地址部分,你在进行C语言指针编程中,可以读取 指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前 进程数据段的地址
线性地址(Linear Address) 是逻辑地址到物理地址变换之间的中间层。
物理地址(Physical Address) 是指出现在 CPU外部地址总线上的寻址 物理内存的地址信号,是地址变换的最终结果地址。

页式
1.地址结构:
逻辑地址=页号&位移量 
2.地址映射:逻辑地址-->物理地址

段式:
1.地址结构
逻辑地址=段号&段内地址 
2.地址映射:
段页式:
1.地址结构
逻辑地址= 段号 & 段内页号 & 页内地址
2.地址映射:


在页式、段式存储管理中,为获得一条指令或数据,须两次访问内存;而段页式则须三次访问内存 


15. 内存连续分配方式采用的几种算法及各自优劣。


16. 动态链接及静态链接.


17. 基本分页、请求分页储存管理方式。


18. 基本分段、请求分段储存管理方式。


19. 分段分页方式的比较各自优缺点。


20. 几种页面置换算法,会算所需换页数。(LRU用程序如何实现?)


21. 虚拟内存的定义及实现方式。

若执行的程序占用内存很大或很多,则会导致内存消耗殆尽。为解决该问题,即匀出一部分硬盘空间来充当内存使用。当内存耗尽时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。

22. 操作系统的四个特性。

 
        
并发性,共享性,虚拟性,异步性
 
         

23. DMA。

1、中断方式是在数据缓冲寄存区满后,发中断请求,CPU进行中断处理

     DMA方式则是以数据块为单位传输的,在所要求传送的数据块全部传送结束时要求CPU进行中断处理,这样大大减少CPU进行中断处理的次数

      DMA方式不需CPU干预传送操作,不占用CPU任何资源,中断方式是程序切换,每次 操作需要保护和恢复现场,中断次数多,CPU需要花较多的时间处理中断,中断次数多也会导致数据丢失。

2、中断方式的数据传送方向是由设备到CPU再到内存,或者相反。

     DMA方式的 数据传送则是将所传输的数据由设备直接送入内存,或是由内存直接送到设备

24. Spooling。

关于慢速字符设备如何与计算机主机交换信息的一种技术,通常称为"假脱机技术"

25. 外存分配的几种方式,及各种优劣。

连续分配

创建文件时,分配一组连续的块;FAT中每个文件只要一项,说明起始块和文件的长度。对顺序文件有利。

优点:
  简单。适用于一次性写入的操作

支持顺序存取和随机存取,顺序存取速度快

所需的磁盘寻道次数和寻道时间最少(因为由于空间的连续性,当访问下一个磁盘块时,一般无需移动磁头,当需要磁头移动,只需要移动一个磁道。

缺点:
文件不能 动态增长(可能文件末尾处的空块已经分配给别的文件)

不利于文件插入和删除

外部碎片问题(反复增删文件后),使得很难找到空间大小足够的连续块。进行紧缩在创建文件时声明文件的大小。

链式分配
  一个文件的信息存放在若干不连续的物理块中,各块之间通过指针连接,前一个物理块指向下一个物理块。FAT中每个文件同样只需要一项,包括文件名、起始块号和最后块号。任何一个自由块都可以加入到链中。
优点:

提高了磁盘空间利用率,不存在外部碎片问题

有利于文件插入和删除

有利于文件动态扩充

缺点:
  存取速度慢,一般仅适于对信息的顺序存取,不适于随机存取:查找某一个块必须从头开始沿指针进行。

可靠性问题,如指针出错;更多的寻道次数和寻道时间

链接指针占用一定的空间,将多个块组成簇(cluster),按簇进行分配而不是按块进行分配(增加了磁盘碎片)。

文件在 磁盘上的所占空间却不是以Byte为衡量单位的,它最小的计量单位是“簇(Cluster)”。

索引分配
 每个文件在FAT中有一个一级索引,索引包含分配给文件的每个分区的入口。文件的索引保存在一个单独的块中。FAT中该文件的入口指向这一块。

优点:
 保持了链接结构的优点,又解决了其缺点: 按块分配可以消除外部碎片,按大小可变的分区分配可以提高局部性。索引分配支持顺序访问文件和直接访问文件,是普遍采用的一种方式。

满足了文件动态增长、插入删除的要求(只要有空闲块)

也能充分利用外存空间

缺点:
较多的寻道次数和寻道时间.

索引表本身带来了系统开销,如:内外存空间,存取时间


26.自旋锁与互斥锁

自旋锁比较适用于锁使用者 保持锁时间比较短的情况。正是由于自旋锁使用者一般保持锁时间非常短,因此 选择自旋而不是睡眠是非常必要的, 自旋锁的效率远高于互斥锁。信号量和读写信号量适合于 保持时间较长 的情况,它们会导致 调用者睡眠,因此只能在进程上下文使用,而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共享资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在 中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就 必须使用自旋锁。自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP(多处理器)的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作。另外格外注意一点:自旋锁不能递归使用
总之:
1)自旋锁由于 不会导致调用者睡眠,而是选择自旋,所以适用于保持锁比较短的情况。效率比较高。
2)自旋锁可以用于进程上下文和中断上下文,而 互斥锁只能用于进程上下文。理由3好像可以解释
3)自旋锁保持锁期间,抢占式失效的。自旋锁只有在内核中使用。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值