CS面试

CS面试


整理的答案直接背记不住,建议去B站找到该问题相关的知识详细了解之后再根据答案学习或者参考。一些内容较多、不好写字描述的问题我直接放了相关讲解的视频。
B站计算机网络:
B站数据结构:

计算机基础

计算机网络

-get请求和post请求的区别

 答:get是从指定资源请求数据,而post是向指定资源提交**被处理**的数据。get和post其实本质上都是TCP连接,get请求数据时只会发送一个数据包,post请求会产生两个数据包。
get在请求时发送的包包含了header和data,服务器接受到后就会返回状态码200。post则是先发送一个包含header的包,等到服务器返回100,之后会发送第二个包含data的包,服务器返回200。

高级解答:https://zhuanlan.zhihu.com/p/114846445?utm_source=qq&utm_medium=social&utm_oi=822127615618973696

get、post、header、body讲解:https://www.bilibili.com/video/BV1bZ4y1W7c7?from=search&seid=1516783352715522411

-在浏览器输入一个URL之后知道浏览器显示页面的过程(可能会详细考察DNS服务器知识)

简单版回答:
1.操作系统解析DNS并返回给浏览器服务器IP地址
2.浏览器同拿着解析到的IP地址与目标服务器建立TCP连接
3.浏览器发送HTTP请求
4.服务器处理请求并返回http报文
5.浏览器解析并渲染页面
复杂版答案:
1.浏览器查询缓存,如果缓存存在跳到第9步。
2.浏览器询问操作系统服务器的IP地址。
3.操作系统做DNS查询,返回IP地址给浏览器。
4.浏览器打开对服务器的TCP连接(如果是HTTPS协议的话会更复杂)。
5.浏览器通过TCP连接发送HTTP请求。
6.浏览器接收HTTP响应并且可能关掉TCP连接,或者是重新使用连接处理新请求。
7.浏览器检查HTTP响应是否为一个重定向(3xx 结果状态码 ),一个验证请求(401),错误(4xx 5xx)等等,这些都是不同响应的正常处理(2xx).
8.如果响应可缓存,将存入缓存。
9.浏览器解码响应(例如:如果它是gzziped压缩)。
10.浏览器决定如何处理这些响应(例如,它是HTML页面,一张图片,一段音乐)。
11.浏览器展现响应,对未知类型还会弹出下载对话框。

-TCP三次握手和四次挥手的过程

三次握手的过程
1)主机A向主机B发送TCP连接请求数据包,其中包含主机A的初始序列号seq(A)=x。(其中报文中同步标志位SYN=1,ACK=0,表示这是一个TC
P连接请求数据报文;序号seq=x,表明传输数据时的
第一个数据字节的序号是x);
2)主机B收到请求后,会发回连接确认数据包。(其中确认报文段中,标识位SYN=1,ACK=1,表示这是一个TCP连接响应数据报文,并含主机B
的初始序列号seq(B)=y,以及主机B对主机A初始序列
号的确认号ack(B)=seq(A)+1=x+1)
3)第三次,主机A收到主机B的确认报文后,还需作出确认,即发送一个序列号seq(A)=x+1;确认号为ack(A)=y+1的报文;
四次挥手过程
假设主机A为客户端,主机B为服务器,其释放TCP连接的过程如下:
1)关闭客户端到服务器的连接:首先客户端A发送一个FIN,用来关闭客户到服务器的数据传送,然后等待服务器的确认。其中终止标志位FIN=1,
序列号seq=u。
2)服务器收到这个FIN,它发回一个ACK,确认号ack为收到的序号加1。
3)关闭服务器到客户端的连接:也是发送一个FIN给客户端。
4)〕客户段收到FIN后,并发回一个ACK报文确认,并将确认序号seq设置为收到序号加1。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

-为什么是三次握手而不是两次握手,为什么是四次挥手,为什么第三次挥手后客户端要等待2MSL

为什么是三次握手:
为了防止过时报文重复连接导致混乱。考虑客户端像服务器请求连接,由于网络某种原因,第一次请求之后没有收到服务器的响应,于是再次请求并成功建立连接。当服务器和客户端传输完成之并断开连接之后,第一次发出的连接请求被服务器接收到,服务器返回响应报文, ack+1。客户端收到服务器的报文之后,判断该连接为响应是由于网络网络原因引起的重复链接,于是第三次握手返回RST报文,表示拒绝连接。如果只是两次挥手,那么该链接成立。
详见:https://www.zhihu.com/question/271701044/answer/1279809269
为什么等待2MSL:
MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
第四次挥手之后可能有两种情况:1)客户端的响应报文被服务器接收,成功断开连接,没有响应。这种情况考虑1个MSL。2)服务器没有接收到响应报文,那么服务器会重复第三次挥手的过程,向客户端发送断开连接的请求报文,客户端收到请求后返回响应报文。这种情况耗时2MSL。两种情况取最大,则为了保证后续连接正常进行,第三次挥手之后客户端需要等待2MSL。若不等待,则后续新建的连接可能会误收到来自服务器的重传断开连接请求,对传输造成影响。

-为什么是四次挥手

因为被动关闭的一方可能还有正在发送的数据,需要完成数据的发送再关闭。两主机的都请求断开才算正式断开,所以是四次。

-七层网络模型和五层网络模型以及各层中的协议

网络模型直接上视频:[https://www.bilibili.com/video/BV14A411E7d5?from=search&seid=3011195411452733203](%E7%9B%B4%E6%8E%A5%E4%B8%8A%E8%A7%86%E9%A2%91%EF%BC%9Ahttps://www.bilibili.com/video/BV14A411E7d5?from=search&seid=3011195411452733203)

各层中的协议:
在这里插入图片描述

-MSL、TTL、RTT的区别

搬运:MSL、TTL及RTT的区别

-TCP与UDP的区别及应用场景

TCP是面向连接的、传输可靠的、端到端的、面向字节流的,常用于对数据完整性要求较高的传输任务,比如:HTTP、FTP等

UDP是非连接的、近最大努力交付(不保证一定到)、一台服务器能同时向多台客户端发送相同的消息、面向报文的,效率更高。可用于IP电话、视频会议、流媒体等对实时性要求高的应用,这类应用中,可靠传输传输并不是最重要的,少量的数据丢失是可以容忍的,但是较大的延时是不能接受的。

TCP的首部占20字节:包括源端口、目的端口、序列号、确认号、数据偏移、保留字段、六个标志位,窗口大小、校验和和紧急指针。

UDP的首部占8字节(首部传输开销更小):仅包含源端口号、目的端口、报文长度(包括首部和报文)、和校验和。

-TCP为什么可靠

[1] 确认和重传机制
建立连接时三次握手同步双方的“序列号 + 确认号 + 窗口大小信息”,是确认重传、流控的基础

传输过程中,如果Checksum校验失败、丢包或延时,发送端重传。

[2] 数据排序

TCP有专门的序列号SN字段,可提供数据re-order

[3] 流量控制

滑动窗口和计时器的使用。TCP窗口中会指明双方能够发送接收的最大数据量,发送方通过维持一个发送滑动窗口来确保不会发生由于发送方报文发送太快接收方无法及时处理的问题。

滑动窗口动画:https://www.bilibili.com/video/BV1qi4y1V7cz?from=search&seid=8257066129002614673
流量控制讲解:https://www.bilibili.com/video/BV1Lb411G7J1


[4] 拥塞控制

TCP的拥塞控制由4个核心算法组成:

“慢启动”(Slow Start)

“拥塞避免”(Congestion avoidance)

“快速重传 ”(Fast Retransmit)

“快速恢复”(Fast Recovery)

拥塞控制算法讲解:https://www.bilibili.com/video/BV1L4411a7RN

为什么收到三个荣誉的ACK才超时重传

-DNS解析过程

1、在浏览器中输入www  . qq  .com 域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
2、如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。 
3、如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/ip参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。 
4、如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。 
5、如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(http://qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找http://qq.com域服务器,重复上面的动作,进行查询,直至找到www  . qq  .com主机。 
6、如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。     从客户端到本地DNS服务器是属于递归查询,而DNS服务器之间就是的交互查询就是迭代查询。

转载自:https://www.zhihu.com/question/23042131/answer/66571369

-怎么实现UDP的可靠传输

要求协议的使用者在应用层实现类似TCP协议的功能保证可靠传输。类似包括:确认和重传、数据排号、滑动窗口、拥塞控制。
新兴的比如在线游戏服务(游戏运行在服务器,客户端负责将键鼠操作传输到服务器和现实从服务器收到的画面),不仅需要信息传输速度快,同时也对传输的可靠性有要求。

-HTTP和HTTPS的区别

1)https协议要申请证书到ca,需要一定经济成本;
2) http是明文传输,https是加密的安全传输;
3)连接的端口不一样,http是80, https是443
4) http连接很简单,没有状态;https是ssl加密的传输,身份认证的网络协议,相对http传输比较安全。

-HTTP常见请求方式和状态码

常见请求方式:
参考:https://www.php.cn/http/http-methods.html

常见状态码:

状态码描述
200成功 Success
301永久跳转 Moved Permanently
302临时跳转 Moved Temporarily
304未改变 Not Modified
403权限不足 Forbidden
404没有找到 Not Found
500服务端内部错误 Internel Server Error
503服务端网关错误 Bad Gateway
504服务端网关超时 Gateway Timeout

详细见RFC2616

HTTP状态码分组:

状态码状态类别
2XX成功
3XX重定向
4XX本地错误
5XX服务器端错误

-HTTPS加密过程/SSL四次握手

在这里插入图片描述

1、client 向 server 发起明文的通信请求,请求包括自己支持的安全协议的版本,能够使用的加密套件的列表,客户端随机数等相关信息。这被叫做ClientHello请求。
2、server收到客户端请求后,server 向 client 回应 “hello” 请求,回应包括服务器选择此次握手使用的协议版本,哪种加密套件,自己的证书,和客户端随机数。这叫做SeverHello。
3、客户端收到服务器的响应之后验证 server 的证书,并抽取公钥。用服务器公钥加密pre_master_key。再用客户端与服务器随机数加上pre_master_key生成shared_sceret_key,再用shared_sceret_key加密一段内容X。将pre_master_key和X都发送给server。
4、服务器收到客户端的加密pre_master_key和X之后,用自己的私钥解密得到pre_master_key。同样使用客户端随机数、服务器随机数和pre_master_key得到shared_secret_key,并用shared_secret_key解密X看X是否符合协议。再用shared_sceret_key加密X并发送给客户端

5.客户端解密X验证,握手完成,往后所有的传输都用shared_secret_key加密传输。

参考:
https://zhuanlan.zhihu.com/p/64724014?utm_source=qq&utm_medium=social&utm_oi=822127615618973696
https://zhuanlan.zhihu.com/p/156034207?utm_source=qq&utm_medium=social&utm_oi=822127615618973696

-如何理解子网掩码

子网掩码的作用是将某个IP地址划分成网络地址和主机地址两部分,必须同IP地址一起使用。子网掩码跟IP地址一样,都是32位的二进制数。将我们常看到的子网掩码转换成二进制之后就变成了32位01组成的数字,将其与二进制的ip地址一一对应,子网掩码为1的部分的ip地址是网络地址,子网掩码为0的部分的ip地址是主机地址。例如:

//IP地址
192.168.25.36

//子网掩码
255.255.255

转换成二进制之后为:

//IP地址
11000000.10101000.00011001.00100100

//子网掩码
11111111.11111111.11111111.00000000

那么IP地址的00100100也就是十进制的36是主机地址。

操作系统

-进程与线程的区别(还有可能有协程)

进程与线程的区别

  1. 进程是CPU资源分配的基本单位,线程是独立运行和独立调度的基本单位(CPU上真正运行的是线程)。
  2. 进程拥有自己的资源空间,一个进程包含若干个线程,线程与CPU资源分配无关,多个线程共享同一进程内的资源。
  3. 线程的调度与切换比进程快很多。
  4. 进程阻塞溃不会影响别的进程。但是,线程有自己的堆栈空间,但是没有独立的地址空间,一个线程阻塞,整个进程就阻塞 。

协程
协程,又称微线程,纤程,是一种用户态的轻量级线程。

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

-协程的好处:

无需线程上下文切换的开销
无需原子操作锁定及同步的开销
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

-缺点:

无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

参考:https://zhuanlan.zhihu.com/p/70256971

linux中如何杀死进程

使用kill指令

kill pid

操作系统的中断和异常

参考:https://zhuanlan.zhihu.com/p/127945132
中断(也称外中断): 指的是来自CPU指令以外的事件。例如I/O设备发出I/O中断请求。或者时钟中断,表示固定时间片用完,让处理机处理计时、定时启动等任务。

陷入(Trap): 陷入为程序故意而为之,为了让CPU进入内核态完成程序的某些功能,常见于系统调用。用户程序运行在用户态,而一些与硬件操作的方法运行在内核态,用户态程序不能直接操作程序,需要利用系统调用让CPU进入内核态帮程序与硬件交互,并返回给程序从硬件处得到的信息。

**异常:**程序执行时发生错误,例如非法的操作码、地址越界、算数溢出、虚拟内存缺页等,也可能是程序中出现除0的代码。

操作系统处理中断的流程为:
(1)运行进程
(2)收到中断信号
(3)保存用户态进程堆栈信息到进程描述符
(4)修改CPU寄存器,将堆栈指针指向当前进程内核态堆栈(切换到内核态)
(5)根据中断中断信号在中断向量表中查到合适的中断处理程序
(6)执行中断处理程序
(7)处理完毕,再次修改寄存器,将堆栈指针指向当前程序用户态堆栈。继续执行程序。

用户态、内核态

参考:https://zhuanlan.zhihu.com/p/21374250
用户态和内核态是CPU的两种运行级别。在用户态,CPU只能执行非特权指令,而在内核态,CPU可以执行所有指令。特权指令包括I/O指令、置终端屏蔽指令、清内存、建存储保护、设置时钟指令等。用户态的进程不能直接控制硬件,需要通过系统调用让CPU进入核心态调用特权指令完成对硬件的操作,将操作结果返回给用户态进程。通过系统调用让用户进程使用系统功能,防止用户态进程对系统数据随意修改,保证系统的安全性和稳定性。除了系统调用,用户态与内核态的切换请查看上一个问题。

进程调度算法

  1. 先来先服务:每次从后备队列的对头选调进程运行。是不可剥夺调度算法,对短作业不友好。适合CPU繁忙行作业。
  2. 短作业优先:每次选调后备队列中估计运行时间最短的进程,为其分配CPU资源。该算法不可剥夺,对长作业不利,可能导致长作业饥饿甚至饿死。
  3. 高相应比:系统为每个进程计算相应比。公式为:
    响 应 比 = 要 求 运 行 时 间 + 已 等 待 时 间 要 求 运 行 时 间 响应比 = \frac{要求运行时间+已等待时间 }{要求运行时间} =+
    该算法对短进程友好,同时兼顾长进程
  4. 优先级调度算法:该算法优先为优先级高的进程分配CPU资源。有金泰优先级、动态优先级。非抢占式优先级、抢占式优先级。
  5. 时间片轮转算法:抢占式调度算法,循环遍历就绪进程队列,为每个进进程分配固定大小的时间片,时间片结束,进程回到队尾。
  6. 多级反馈队列调度:该算法有多级队列。进程优先进入高级的队列,被分配时间片,时间片用完之后会到下一级队列。只有当上一级队列为空时,下一级队列才会开始运行。队列等级越低,优先级越低,但每次分配到的时间片越长。对内采用FIFS方式排队。

linux中几种io模型

来自:https://www.bilibili.com/video/BV1Ka4y177gs/?spm_id_from=333.788.videocard.0

进程通信

进程通信的方法有三类:

  1. 共享存储:在通信的进程间存在可直接访问的共享内存空间,通过对共享内存空间的读写实现进程通信。 共享存储分为两种:低级的基于共享数据结构,高级的基于共享存储区。
  2. 消息传递:两进程通过消息传递实现通信。
    -直接通信方式:发送进程直接把消息发送给接受进程,挂在接受进程的消息缓冲队列上。
    -间接通信方式:发送进程把消息发送到某中间实体,接受进程从实体处取得消息。这一实体通常称为信箱。
  3. 管道通信:管道是一种连接读写进程以实现他们通信的共享文件。管道内的数据是字节流形式的。管道是半双工的,想实现全双工通信需要开两个管道。

连续内存分配的动态内存分配算法

连续内存分配指的是操作系统为应用程序分配的内存空间在物理上是连续的。连续内存分配分为固定内存分配和动态内存分配,固定内存分配指的是操作系统提前将内存划分好固定大小的区域用于分配给应用程序,这种分配方式对内存的利用率低,且有内部碎片。动态内存分配指的是操作系统根据应用程序所占内存大小按照算法动态分配内存中空闲的空间。
动态内存分配算法包括:首次适应、近邻适应(循环首次适应)、最佳适应和最坏适应。

非连续内存分配的内存管理方式

非连续内存分配的内存管理方式有:

1. 分页存储管理方式。这种管理方式中,操作系统将内存划分成固定大小的内存块,叫页帧。应用程序也按同样的大小划分,每一块叫页。程序加载入内存时不再要求一整块连续的内存,只需要将每一页分配一个页帧即可。操作系统维护一个页表,结构为:

页号物理地址

同时,页式存储的地址结构为

页号页内偏移量

当操作系统要访问内存中的内容时,通过逻辑地址的页号按页表查到要访问的页在内存中的物理地址,拿物理地址加上页内偏移量就能得到要访问的逻辑地址在内存中的实际物理地址了。

2. 段式存储管理方式: 页式存储对程序员是透明的,由操作系统完成的。为了方便对程序的管理,从逻辑上将程序按模块划分成段。程序加载入内存时,操作系统为每一个段分配一块内存空间。在段式存储管理中,段间在物理内存中不要求连续,段内在物理内存中是连续的。此时的段表结构为:

段号段长段起始位置

地址结构为:

段号段内偏移量

访问内存中的内容时的过程为:按逻辑地址中的段号查到段表中相应段在内存中的起始位置,然后用起始位置加上偏移量就查询到了要访问内容的实际物理地址。其中的段长是为了防止越界做判断所用。

3.段页式存储管理方式: 这种管理方式是结合以上两种管理方式而产生的,原理类似。系统仍然要维护段表,不过具体的结构变为了:

段号页长页表起始地址

地址结构为:

段号页号页内偏移量

查询时根据逻辑地址查询到段表中相应段对应的页表在内存中的起始位置,随后访问该页表,用逻辑地址中的页号查询到待访问内容所在页在内存中的页起始地址,再加上页内偏移量就得到了实际的物理地址。

虚拟内存管理中的页面置换算法(LRU可考手撕代码)

虚拟内存管理的页面置换算法有:

1.最佳置换算法(OPTIMAL): 即当发生页面置换时,选择已在内存中但是这些内存块中在将来最远被用到的。这个算法要求知道将来发生置换的页面序列,所以只是理论上最好,无法实现。

2.先进先出(First In First Out): 即当发生页面置换时,首先置换出最早进入内存的页。这种算法存在belady异常,即当为虚拟内存分配的物理块数增加时,置换的频率不降反增的现象。

3.最近最久未使用(Least Recently Used): 即当发生页面置换时,选择所分配物理内存块中最近最久未被访问的页置换。该算法为每个页面设置一个访问字段,记录该页自上次被访问以来的时间,置换是选择字段值最大的页面置换。

4.时钟置换算法(CLOCK/ Not Recently Used): 该算法为每一个页面设置一个访问位,被访问即被置为1。 将用于替换的页面集合看作是一个循环缓冲队列,循环扫描。若访问位为1,则将访问位置为零,继续扫描下一个页面。若访问位为0,则置换。所以该算法又叫最近未使用算法

5.改进时钟算法: 在原来的时钟置换算法的基础上,增加了m标记为。此时算法对页面有两个标记位:u(used)和m(modified),都拥有0和1两个状态。寻找置换页时,首先寻找u=0,m=0的页面,如果没有就寻找u=0, m=1的页面。每扫描到一个页面,u都会被置0。尽量保留使用过的页面,淘汰未被使用过的页面。

手撕LRU:牛客NC93

死锁的定义、条件以及避免(银行家算法)

死锁即系统中的多个竞争资源导致的相互等待,若无外力的作用,这些进程都无法向前推进。

死锁的四个条件:
|

互斥即进程所要求的资源在一段时间内只能被一个进程访问
不可剥夺进程申请到了独占资源之后,在使用完之前不能被别的进程强行夺走
请求保持进程已申请到了资源,又申请新资源,但新资源已被别的进程占有,此时申请的进程被阻塞,但是又不主动释放自己拥有的资源。
循环等待队列系统中存在一循环等待队列,队列中的每一个进程所申请的资源都被队列中的下一个元素所占有。

死锁的处理策略分为:死锁的预防、死锁避免和死锁解除。

死锁的预防只需要破环死锁的四个条件之一即可,但是会导致效率低下或者对进程工作的破坏。

死锁的避免是找到一个安全序列,满足安全序列中的对资源的申请即可避免系统发生死锁。死锁避免算法中最著名的算法就是银行家算法

银行家算法模拟银行家放贷。操作系统中的资源就是银行家的资金,进程就是贷款者。银行家在房贷之前先检查借贷者已借金额和目前剩余资金相加是否大于该借贷者的最大借贷金额,如果不满足,倘若把这笔资金借出去,可能会发生资金断裂,导致资金无法回收,也就是产生死锁。这个算法具体的会有三个矩阵:Max、Allocation、Need。Max矩阵存放每个进程对每个资源的最大需求量,Allocation记录系统为各个进程已分配的资源数量。Max矩阵减去Allocation矩阵就会得到Need矩阵,也就是各个进程接下来所需要的资源数。除了这三个矩阵,系统还维护一个Available向量,其中保存着系统中各个资源的剩余量。
-银行家算法描述
Pi[j]表示进程Pi请求的j资源的数量
(1)判断 if (Pi[j] <= Need[i, j]), 否则申请量大于该进程宣布的对该资源申请的最大值,不予分配。
(2)若第一步通过,判断 if (Pi[j] <= Available[j]), 否则剩余资源小于该进程申请资源量,不给予分配。
(3)若(1)和(2)通过,系统修改一下数据
Available[j] = Available[j] - Pi[j];
Allocation[i, j] = Allocation[i, j] + Pi[j];
Need[i, j] = Need[i, j] - Pi[j];
(4)执行安全性算法,如果安全性算法能够找到一个安全序列,就将进程申请的资源正式分配给进程,否则数据修改退回,不予进程分配资源。

安全性算法:
这里直接写伪代码了

vector<vector<int>> result;
vector<int> path;

vector<int> security(){
	findPath(Max, Need, Max.size());
	return result;
}

void findPath(Max, Allocation, Available, lenght){
	if (path == length) {
		result.push_back(path);
		return;
	}
	Need= Max - Allocation;
	for(int i=0; i<Max.size(); i++){
		if(Available - Need[i] >= 0){
			MaxTemp = Max - Max.pop(i); //Max去掉第i行
			AllocationTemp = Allocation - Allocation.pop(i);
			AvailableTemp = Available +  Allocation[i];
			path.push_back(i)
			findPath(MaxTemp, AllocationTemp, AvalilableTemp, length);
			path.pop();
		}
	}
}

进程的五态、线程的七态模型

进程的五个状态:

  • 创建:进程正在被系统创建
  • 就绪:进程处于可运行状态,拥有运行的一切资源,得到CPU即可运行
  • 阻塞:进程在等待某一事物而暂停
  • 运行:正在处理机上运行
  • 结束:进程运行结束或异常退出,正在从系统中消失

五个状态的切换:

  • 就绪->运行:进程获得处理机资源
  • 运行->就绪:时间片用完
  • 运行->阻塞:请求资源,例如等待IO
  • 阻塞->就绪:请求的资源已分配

线程的七个状态:
与进程相比多了两个状态:

  1. 无限期等待(Waiting)状态 synchronized 代码块内被锁住的对象调用了它的 wait() 方法或者在当前线程中调用了其他线程的 join() 方法,那么当前线程将会释放占有的锁,释放 CPU 资源,阻塞在等待队列里面,一直等待被 synchronized 修饰的对象调用 notify() 或 notifyAll() 方法唤醒或者 join 的其他线程执行结束(异常退出)。在并发时,处于无限期等待状态的线程被唤醒之后,还要去竞争对象的锁,如果竞争不到,线程将会被阻塞在对象的锁池中,竞争到锁之后,线程将会处于 Runnable 状态。
  2. 限期等待(Timed Waiting)状态 与无限期等待(Waiting)状态不同之处在于,调用 wait 和 join 方法时传入了等待限定时间。另外,线程调用 sleep() 方法也会处于限期等待(Timed Waiting)状态,会释放 CPU 资源,但并不会释放锁,一直到休眠结束变成 Runnable 状态。

进程的同步与互斥

进程同步是进程与进程间的直接制约问题,进程互斥是进程与进程间的间接制约问题。
进程的同步时指两个或以上的进程为了完成某个任务,在某个位置上需要协调工作而产生的等待和消息传递所产生的制约关系。
互斥 即当一个进程进入占有临界资源时,其他进程必须等待该进程释放临界资源才能申请使用。

进程的同步与互斥都由信号量机制完成。

线程的同步

动态链接库与静态链接库

数据结构

-判断链表是否有环,并且输出环入口节点

1.快慢指针法,转自:https://mp.weixin.qq.com/s/_QVP3IkRZWx9zIpQRgajzA
快慢指针法找环入口需要数学计算,还是比较复杂的,但是是三种方法中不破坏链表原结构,空间复杂度也最低的一种

2.利用集合的性质:遍历链表,每遍历到一个节点先检查改节点是否已经存在于集合中,若已存在,则该点为环入口,若不存在,则加入集合。

3.让节点指向自己:每遍历到一个节点,就判断{if (node ==node->next)},如果成立,则该节点为环的入口,若不是,则将节点的next指针指向自己。当然,期间需要利用一个temp指针先保存next指针指向的节点。其实这种方法是将节点标记,标记的方式就是节点是否指向自身。第一个找到的标记节点就是环入口。

总结:快慢指针法需要计算,比较麻烦,但是空间复杂度低。第二三种方法方便理解,但是需要辅助空间或者会破坏链表本身结构。如果只是问链表是否有环,第一种解法也是比较方便的。

-二分查找

二分查找的思路很简单,但是在实际写代码的时候常会因为一些细节问题导致代码不通过,强烈安利这种思路的二分查找法,二分查找再也不会写错了!

-有了二叉平衡树为什么还要红黑树

平衡二叉树拥有良好的查找性能(O(logN)),但是删除和插入的效率低下,删除和插入操作大概率因此树的调整,所以效率低。而红黑树不仅查找效率高,插入和删除的效率也高(查找、删除、插入都是O(logN))。

-常见排序算法及时间复杂度

二叉树和B树的区别

B树和B+树的区别

hashMap解决hash冲突的几种方式

霍夫曼编码

数组和链表的区别

数组在内存中是连续的,链表的元素是不连续的。数组查找方便,但是增删会有大量的元素需要移动。链表增删方便,但是查找起来只能沿着链表遍历。

10W条数据图和找出前一百条频繁数据

100个有序数列合并成一个大数组

数据库

-SQL语句中where、group by、having、order by、 limit的执行顺序以及查询语句的执行顺序。

SQL中的这些关键字是按照如下顺序进行执行的:where->group by->having->order by->limit。

还要注意:where值作用于分组前的数据,having之作用于分组后的数据。

语句的执行顺序:

select *					[7]
from table					[1]
where XXX1					[2]
group by XXX				[3]
having XXX					[4]
order by XXX				[5]
limit XXX					[6]
;

第一行实际是最后执行的,所以在第一行给某值取别名(as语句)并且在后面的行中直接使用别名会报错,例如:

select id, sum(orders) as s		#定义别名
from reocrd
group by id
having s>5000	#这里的s实际是未定义的,应用sum(orders)>0
;

-MySQL的ACID

-四大 隔离级别

-不同数据库的区别(Redis、MySQL、MongoDB)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值