操作系统面试知识点

笔记 专栏收录该内容
7 篇文章 0 订阅

操作系统面试知识点


https://www.nowcoder.com/discuss/325668?type=5 重要连接,很多操作系统面试知识点

什么是操作系统?
操作系统(英语:operating system,缩写作 OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。

请描述进程的三种基本状态?
就绪状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
执行状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
阻塞状态:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

进程状态间的切换?
(1) 就绪→执行
处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程便由就绪状态转变成执行状态。
(2) 执行→就绪
处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完而不得不让出处理机,于是进程从执行状态转变成就绪状态。
(3) 执行→阻塞
正在执行的进程因等待某种事件发生而无法继续执行时,便从执行状态变成阻塞状态。
(4) 阻塞→就绪
处于阻塞状态的进程,若其等待的事件已经发生,于是进程由阻塞状态转变为就绪状态。

线程的几种状态?
线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态;
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪状态。

什么是线程?
线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。(线程自身是不能拥有系统资源的,但是它可以拥有自己的栈、局部变量以及程序计算器。并且线程共用一个进程里面的堆空间)
优点:可以提高系统的并行性,数据共享比较方便,切换比较快。
缺点:没有内存隔离,一个线程的崩溃会导致整个进程的崩溃。编程复杂以及调试困难。

什么是进程?
进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发;
优点:内存隔离,单个进程的崩溃不会导致这个系统的崩溃。而且进程方便测试以及编程简单
缺点:创建销毁比较麻烦,进程间数据的共享麻烦,并且消耗的资源比较多。

一个进程里包含什么?
一个进程由三部分组成:程序、数据及进程控制块(PCB)。进程控制块是记录进程有关信息的一块主存,是进程存在的程序唯一标识。

进程和线程区别?
调度: 线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
并发性: 不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行
拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源
系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,I/O设备等,OS所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销

进程和线程的关系?
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)
资源分配给进程,同一进程的所有线程共享该进程的所有资源
线程在执行过程中,需要协作同步,不同进程的线程间要利用消息通信的方法实现同步
处理机分配给线程,即真正在处理机上运行的是线程
线程是指进程内的一个执行单元,也是进程内的可调度实体

并发跟并行的理解:
1、并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。(多个进程在一个时间段看似同时进行叫并行,并且并行必须要在多处理器系统中才能存在,一个处理器同时只能处理一个进程,不能实现并行)
2、并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。(并发可以在单处理器或多处理器上实现。当有多个线程在操作时,如果系统只有一个 CPU,则它根本不可能真正同时进行一个以上的线程,它只能把 CPU 运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状态.这种方式我们称之为并发(Concurrent)。

线程有哪些基本状态?这些状态是如何定义的?
新建(new):新创建了一个线程对象。
可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取cpu的使用权。
运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。
阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有 机会再次获得cpu timeslice转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放 入等待队列(waiting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步 锁 被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞: 运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
死亡(dead):线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
在这里插入图片描述备注: 可以用早起坐地铁来比喻这个过程(下面参考自牛客网某位同学的回答):

还没起床:sleeping
起床收拾好了,随时可以坐地铁出发:Runnable
等地铁来:Waiting
地铁来了,但要排队上地铁:I/O阻塞
上了地铁,发现暂时没座位:synchronized阻塞
地铁上找到座位:Running
到达目的地:Dead

何为多线程?
多线程就是多个线程同时运行或交替运行。单核CPU的话是顺序执行,也就是交替运行。多核CPU的话,因为每个CPU有自己的运算器,所以在多个CPU中可以同时运行。

为什么多线程是必要的?
使用线程可以把占据长时间的程序中的任务放到后台去处理。
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
程序的运行速度可能加快。

使用多线程常见的三种方式?

①继承Thread类 ②实现Runnable接口 ③使用线程池

Java多线程分类?
①用户线程
运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程
②守护线程
运行在后台,为其他前台线程服务.也可以说守护线程是JVM中非守护线程的 “佣人”。

特点: 一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作
应用: 数据库连接池中的检测线程,JVM虚拟机启动后的检测线程
最常见的守护线程: 垃圾回收线程
如何设置守护线程?

sleep()方法和wait()方法简单对比?
两者最主要的区别在于:sleep方法没有释放锁,而wait方法释放了锁 。
两者都可以暂停线程的执行。
Wait通常被用于线程间交互/通信,sleep通常被用于暂停执行。
wait()方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的notify()或者notifyAll()方法。sleep()方法执行完成后,线程会自动苏醒。

为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
这是另一个非常经典的java多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都会答不上来!
new一个Thread,线程进入了新建状态;调用start()方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start()会执行线程的相应准备工作,然后自动执行run()方法的内容,这是真正的多线程工作。 而直接执行run()方法,会把run方法当成一个mian线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
总结: 调用start方法方可启动线程并使线程进入就绪状态,而run方法只是thread的一个普通方法调用,还是在主线程里执行。

AtomicInteger原子类的知识点:能够保证原子性。
Volatile能够保证可见性,但是不能保证原子性,所以要用AtomicInteger原子类。

什么是进程间通信?通信的目的?
进程通信:
进程用户空间是相互独立的,一般而言是不能相互访问的。但很多情况下进程间需要互相通信,来完成系统的某项功能。进程通过与内核及其它进程之间的互相通信来协调它们的行为。
目的:
数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。
共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

进程间通信方式-IPC?哪种方式效率最高?
1.匿名管道( pipe ):父子进程间或兄弟进程间
2.有名管道 (named pipe) : 任意进程
3.信号量( semophore ) :
4.信号(sinal):信号是Linux系统中用于进程间互相通信或者操作的一种机制,信号可以在任何时候发给某一进程,而无需知道该进程的状态。
5.消息队列( message queue ) : 消息队列允许一个或多个进程向它写入与读取消息.
6.共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
7.套接字( socket ) :套接字是一种通信机制,凭借这种机制,客户/服务器(即要进行通信的进程)系统的开发工作既可以在本地单机上进行,也可以跨网络进行。

最快的方式是共享内存:采用共享内存通信的一个显而易见的好处是效率高,**因为进程可以直接读写内存,而不需要任何数据的拷贝。**对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝

用户态内核态:(简单理解就是系统为了自我保护,定义了内核态,即进程运行特权指令时候处于的状态,定义了用户态,即普通进程运行非特权指令时候所处于的状态。当处于用户态时候,也可能由于文件读写,中断处理等情况而从用户态转换为内核态)
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

局部性原理
(1)时间局部性:如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。
这当然是正确的,用过的数据当然可能再次被用到。
(2)空间局部性:在最近的将来将用到的信息很可能与现在正在使用的信息在空间地址上是临近的。
正在使用的这个数据地址旁边的数据,当然也是很可能被用到的。比如数组什么的
(3)局部性原理一定程度上解释了缓存的存在。

缺页中断是什么?有哪几种算法对应?
回答:缺页中断:要访问的页不在主存,需要操作系统将其调入主存后再进行访问。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
总结:缺页中断次数越少越好,不浪费空间资源,进程能够最优进行。

mmu是什么?
内存管理单元是介于处理器和片外存储器之间的中间层。提供对虚拟地址(VA)向物理地址(PA)的转换。(MMU其实是一个硬件。当虚拟地址:也就是每个进程看似拥有1TB磁盘和8G内存的内存空间,实际上当内存中缺页的时候,就会通过MMU去管理,调取磁盘中相应的页到内存进行处理,所以我们说MMU功能是提供虚拟地址向物理地址的转换)
数据库主键和索引区别?
回答:

  1. 主键一定是唯一性索引,唯一性索引并不一定就是主键。一个表只能有一个主键,但可以有多个候选索引。因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。数据库在设计时,主键起到了很重要的作用。
  2. 一个表中可以有多个唯一性索引,但只能有一个主键。
  3. 主键列不允许空值,而唯一性索引列允许空值。
  4. 索引可以提高查询的速度。

ping过程发生了什么?(实际上发送的是ICMP的请求包,接受方收到后会返回ICMP响应包)
回答:不考虑域名解析、ARP 广播、路由转发、各种校验的简化版:
ping 192.168.0.4  ---->  构建 ICMP 包  ---->  构建 IP 分组  ---->  解析硬件地址封装成帧  ---->    物理层发送
接收方就是反过来拆包的过程。

redis的set底层是怎么实现的?
回答:是由一个数组和一个hashtable组成的,而对于java,set底层基本上都是实现了一个map。

虚拟内存的定义?
解答:
虚拟内存通过内存地址转换解决了多个进程访问内存冲突的问题,通过内存管理单元MMU来将虚拟内存上的虚拟地址转换为内存的物理地址,虚拟内存是以4k为页单位的一个表,来映射所有的内存物理地址。
在这里插入图片描述
由于如果每次开启一个进程就分配4G的物理内存的话,内存将不够用,所以需要虚拟内存。
实际中,创建一个进程会分配4G的虚拟内存,但是实际上只对应磁盘中的一点点。

进程得到的这4G虚拟内存是一个连续的地址空间(这也只是进程认为),而实际上,它通常是被分隔成多个物理内存碎片,还有一部分存储在外部磁盘存储器上,在需要时进行数据交换。

进程访问一个地址的过程:
(1)访问地址空间的时候,将虚拟地址转换为实际物理地址。由MMU(内存管理单元)负责。
(2)由于虚拟地址中的数据,有些是在物理内存上,有些是在磁盘中,所以需要业表来记录。
(3)业表如下:页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
在这里插入图片描述(4)进程访问虚拟地址的时候,先看业表,如果不在物理内存中,则发生缺页中断。
(5)缺页异常的处理过程,操作系统立即阻塞该进程,并将硬盘里对应的页换入内存,然后使该进程就绪,如果内存已经满了,没有空地方了,那就找一个页覆盖,至于具体覆盖的哪个页,就需要看操作系统的页面置换算法是怎么设计的了。

【重点】IO多路复用:
解答:
一、定义:
「定义」
IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu。多路是指网络连接,复用指的是同一个线程
二、背景:
(1)没有IO多路复用机制时,有同步阻塞BIO、同步非阻塞NIO两种实现方式,但有一些问题。
在这里插入图片描述在这里插入图片描述三、select
在这里插入图片描述在这里插入图片描述
四、poll与select相比,只是没有fd的限制,其它基本一样。

五、关于epoll
在这里插入图片描述
epoll LT 与 ET模式的区别?
epoll有EPOLLLT和EPOLLET两种触发模式,LT是默认的模式,ET是“高速”模式。
LT模式下,只要这个fd还有数据可读,每次 epoll_wait都会返回它的事件,提醒用户程序去操作。
ET模式下,它只会提示一次,直到下次再有数据流入之前都不会再提示了,无论fd中是否还有数据可读。所以在ET模式下,read一个fd的时候一定要把它的buffer读完,或者遇到EAGAIN错误。
在这里插入图片描述
关于select,poll,epoll的讲解https://juejin.im/post/6844904200141438984

阻塞BIO和非阻塞NIO的区别:
1、阻塞BIO发起IO请求的时候。
在这里插入图片描述
由内核去查看数据是否就绪(也就是是否有数据进来),如果没有的话,应用程序就会进入到阻塞状态,等待内核准备好数据。
2、阻塞BIO当用户程序进行阻塞的时候,是会将CPU资源交给其他应用程序使用,所以相对非阻塞IO一直占用CPU资源来说
,相对性能更好。
在这里插入图片描述select 和 epoll的形象介绍:
在这里插入图片描述
redis使用的io模型?nginx使用哪些模型?
解答:redis使用io多路复用模型,内包含了select , epoll(Linux下,不同操作系统实现不同)等函数功能。
nginx也都支持select poll epoll,但是默认选择效率最高的epoll。

【Linux操作系统知识】
内存分布与内存管理方式?
回答:
内存分配的两种方式:(1)连续内存分配方式 (2)离散内存分配方式

(1)连续内存分配方式:
固定分区分配:将内存划分成若干个固定大小的块。将程序装入块中即可。内存划分成各个块之后,块大小不再改变。当然,划分块的方式有:所有的块大小相等;划分的块大小不相等。这种方式,在实际的内存分配之前,就已经知道了所有的内存块大小了。
动态分区分配:需要一个空闲表 或者 空闲链 来记录目前系统中空间的内存区域。在内存分配时,需要查找空间表或空闲链找到一块内存分配给当前进程。
动态分区分配算法:
a)首次适应法
b)循环首次适应法
c)最佳适应法
d)最坏适应法
e)快速适应法
可重定位分区分配:
说白了,就是增加了内存移动的功能。由于若干次内存分配与回收之后,各个空闲的内存块不连续了。通过“重定位”,将已经分配的内存“紧凑”在一块(就类似于JVM垃圾回收中的复制算法)从而空出一大块空闲的内存出来。”紧凑“是需要开销的,比如需要重新计算 地址,这也为什么JVM垃圾回收会导致STW的原因。而离散分配方式–不管是分页还是分段,都是直接将程序放到各个离散的页中。从而就不存在“紧凑”一说了。

(2)离散内存分配方式
在这里插入图片描述分页存储管理:(https://www.cnblogs.com/hapjin/p/5689049.html 、 https://blog.csdn.net/AudienceT/article/details/84920013)
作业规定大小划分成小份;内存也按同样大小划分成小份
作业的任一小份可分散放入内存任意未使用的小份
业表的概念(页号到物理块号的地址映射):为了找到被离散分配到内存中的作业,记录每个作业各页映射到哪个物理块,形成的页面映射表,简称页表。每个作业有自己的页表。
在这里插入图片描述分段存储管理:与分页相似。

1、内核台,用户态的转换
2、死锁发生的条件,死锁预防,死锁解除
3、垃圾回收算法
4、jdk8 hashmap中为什么链表改成红黑树,为什么不用平衡树那些
5、计算机网络TCP如何实现拥塞控制

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值