【腾讯】WXG视频号面经,撑到了二面|0315

alt

1. 操作系统的内存分配设计原理

解析:

OS 常见题,难度中等,考察频率适中。

参考答案:

操作系统的内存分配设计原理主要基于虚拟内存、内存分页、内存分段以及多种内存分配算法。

  1. 虚拟内存:操作系统为每个进程分配一个虚拟地址空间,这个空间远大于实际的物理内存。进程在运行时,其所需的代码、数据等被映射到虚拟地址空间中。当进程需要访问某个虚拟地址时,如果该地址对应的物理内存页尚未加载,则发生缺页中断,操作系统负责将该页从磁盘或其他存储介质加载到物理内存中。这种方式有效地扩展了可用内存,使得程序可以像使用大内存一样运行。
  2. 内存分页:操作系统将物理内存划分为固定大小的页,每页的大小通常是固定的,如4KB。同样,虚拟地址空间也被划分为页。当进程需要访问某个虚拟页时,操作系统通过页表查找该页对应的物理页。如果物理页不存在,则触发缺页中断。
  3. 内存分段:与分页不同,分段是根据程序的逻辑结构来划分内存的。每个段都有自己的名称和长度,并且可以有不同的访问权限。这种方式可以更好地管理程序的内存使用,但实现起来相对复杂。
  4. 内存分配算法:操作系统使用多种算法来管理内存分配,包括首次适应算法、最佳适应算法、最坏适应算法等。这些算法在分配内存时考虑不同的因素,如分配速度、内存碎片等。例如,首次适应算法从空闲链表的起始位置开始查找,找到第一个满足需求的空闲分区进行分配;而最佳适应算法则查找最小的满足需求的空闲分区进行分配,以减少内存碎片。

操作系统的内存分配设计原理是为了高效、公平、安全地管理计算机系统的内存资源。通过虚拟内存、内存分页、内存分段以及多种内存分配算法,操作系统能够在有限的物理内存条件下满足多个进程的运行需求,提高系统的整体性能。

学习参考:十年大佬讲述,操作系统内存管理(图文详解)

面经专栏直通车

面经专栏下载

2. . 操作系统的MMU

解析:

OS 概念题,难度中等,考察频率中等。

参考答案:

操作系统的MMU(Memory Management Unit,内存管理单元)是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路。MMU主要负责虚拟地址到物理地址的映射,以及提供硬件机制的内存访问授权,这在多用户多进程操作系统中尤为重要。

MMU的工作原理主要可以概括为地址转换和访问权限控制两个方面。当CPU发出一个访存请求时,MMU会将逻辑地址转换为对应的物理地址,确保能够准确地访问到内存中的数据。同时,MMU还负责控制内存的访问权限,确保程序只能访问到其拥有权限的内存区域,这有助于提高系统的安全性和稳定性。

在实际的计算机系统中,MMU通常通过页表来实现地址转换和访问权限控制。页表是一个存储在内存中的数据结构,记录了逻辑地址和物理地址之间的映射关系,以及每个页面的访问权限信息。当CPU发出访存请求时,MMU会根据页表中的映射关系将逻辑地址转换为物理地址,并检查访问权限是否合法。

除了页表,MMU还可以通过地址变换缓冲器(TLB)来提高地址转换的效率。当CPU发出访存请求时,MMU会首先在TLB中查找对应的页表项,如果找到则直接进行地址转换,否则再去访问页表。

学习参考:MMU原理

3. malloc 是怎么实现的

解析:

c 语言和 os 综合题,难度中等,考察频率高。

参考答案:

malloc是C语言中用于动态分配内存的函数。它的实现方式可以因编译器和操作系统而异,下面是一种常见的实现方式:

  1. 首先,malloc函数会接收一个参数,即需要分配的内存大小。
  2. malloc函数会检查当前的空闲内存块链表,查找是否有足够大小的空闲内存块。
  3. 如果找到了足够大小的空闲内存块,则将其从空闲内存块链表中移除,并返回该内存块的起始地址给调用者。
  4. 如果没有找到足够大小的空闲内存块,则会进行内存分配。这通常涉及到向操作系统请求更多的内存空间。
  5. 操作系统会分配一块连续的内存空间,并将其标记为已使用。
  6. malloc函数将分配到的内存块的起始地址返回给调用者,并将其添加到已分配内存块链表中,以便后续的内存管理。
  7. 调用者可以使用返回的内存块地址来存储数据。
  8. 当不再需要使用这块内存时,调用者可以使用free函数将其释放,将其重新添加到空闲内存块链表中,以便其他程序可以再次使用。

需要注意的是,malloc函数的实现可能会有一些额外的处理,例如内存对齐、内存池等,以提高内存分配的效率和性能。具体的实现细节可能因编译器和操作系统而异。

学习参考:malloc函数实现原理!

4. 缺页机制的实现

解析:

os 基础题,必会题,面试频率较高。

参考答案:

当程序试图访问一个尚未映射到物理内存中的虚拟页面时,就会发生缺页中断,从而触发缺页机制。以下是缺页机制的基本实现步骤:

  1. 中断触发:当CPU尝试访问一个不在物理内存中的页面时,硬件会生成一个缺页中断。这个中断会暂停当前程序的执行,并将控制权交给操作系统。
  2. 中断处理:操作系统捕获到缺页中断后,会开始缺页处理流程。首先,它会检查发生缺页中断的虚拟页面的信息。这些信息通常保存在一个特殊的硬件寄存器中,或者通过检查程序计数器和分析当前指令来获取。
  3. 页面分配:一旦确定了需要加载的页面,操作系统会在物理内存中查找一个空闲的页框(Frame)。如果找不到空闲页框,它可能会选择一个当前正在使用的页框进行置换,这个过程通常涉及到页面置换算法(如LRU、FIFO等)来决定哪个页面应该被替换。
  4. 页面调入:当找到空闲页框后,操作系统会从磁盘等辅助存储器中加载相应的页面内容到该页框中。这通常涉及到磁盘I/O操作,因此可能是缺页处理中耗时较长的一个步骤。
  5. 更新页表:页面加载完成后,操作系统会更新页表,将虚拟页面的映射关系更新为新的物理页框。这样,当程序再次访问该页面时,就可以直接从物理内存中获取数据了。
  6. 恢复执行:最后,操作系统会恢复缺页中断发生前的程序执行状态,将程序指令器重新指向引起缺页中断的指令,并继续执行程序。

在整个缺页处理过程中,操作系统需要确保数据的一致性和完整性,同时尽量减少缺页中断对程序性能的影响。这通常涉及到一些复杂的策略和算法,如预取策略、缓存机制等,以优化内存访问的性能。

学习参考:深入理解【缺页中断】

5. select. poll. epoll讲一下底层原理

解析:

操作系统常见题,必会题。

参考答案:

selectpollepoll都是用于实现I/O多路复用的机制。

  1. selectselect是最古老的I/O多路复用机制之一。它通过一个位图来管理文件描述符集合,通过轮询的方式检查每个文件描述符的状态变化。当有文件描述符就绪时,select会返回,然后通过遍历文件描述符集合来确定哪些文件描述符可读、可写或出错。
  2. pollpoll是对select的改进,它使用一个结构体数组来管理文件描述符集合,每个结构体中保存了文件描述符和关注的事件。与select不同的是,poll不需要遍历整个文件描述符集合,而是通过系统调用将文件描述符集合传递给内核,内核会将就绪的文件描述符填充到结构体数组中。
  3. epollepoll是Linux特有的I/O多路复用机制,相对于selectpoll,它具有更高的性能和扩展性。epoll使用了事件驱动的方式,通过将文件描述符添加到内核事件表中,当有事件发生时,内核会通知应用程序。epoll提供了三个系统调用:epoll_create用于创建一个epoll实例,epoll_ctl用于控制事件的注册和删除,epoll_wait用于等待事件的发生。

在底层原理上,epoll利用了Linux内核的事件驱动机制,通过使用红黑树和双链表来管理文件描述符集合,以及利用回调机制来处理就绪的事件。相比于selectpoll的轮询方式,epoll能够更高效地处理大量的文件描述符,并且支持边缘触发和水平触发两种工作模式。

selectpollepoll都是用于实现I/O多路复用的机制,它们在底层原理上有所不同,而epoll相对于selectpoll具有更高的性能和扩展性。

学习参考:Linux下的IO多路复用技术:poll、epoll与select的比较

6. 多路复用epoll相比select和poll的主要改进点是什么?

解析:

操作系统常见题,必会题。

参考答案:

多路复用epoll相比select和poll的主要改进点体现在以下几个方面:

  1. 效率与性能
    • select:select在每次调用时都需要遍历整个文件描述符集合,即使只有少数几个描述符就绪,也会进行无用的遍历,导致效率低下。此外,select能同时处理的文件描述符数量是有上限的,这限制了它在高并发场景下的应用。
    • poll:虽然poll解决了select的文件描述符数量限制问题,并且通过将输入输出参数进行分离来减少每次设定的开销,但它仍然需要遍历整个文件描述符数组来查找就绪的描述符,因此在文件描述符数量很大时,性能依然有限。
    • epoll:epoll通过红黑树和就绪链表来管理文件描述符,并只关注那些状态已经发生变化的文件描述符。这种机制避免了不必要的遍历,从而大大提高了效率。当有大量文件描述符需要监视时,epoll的性能优势尤为明显。
  2. 工作模式
    • select和poll:它们只能工作在低效的LT(水平触发)模式下,即当有事件发生时,需要多次循环处理直到没有事件为止。
    • epoll:支持高效的ET(边沿触发)模式。在这种模式下,当有事件响应时,应用程序必须立即处理。这种机制减少了不必要的轮询和等待,进一步提高了性能。
  3. 事件处理
    • select和poll:采用轮询的方式处理事件,即每次调用时都需要检查所有文件描述符的状态。
    • epoll:采用回调的方式处理事件。当有就绪的文件描述符时,会触发回调函数,将对应的事件插入到内核就绪事件队列中。内核在适当的时机将该队列中的内容拷贝到用户空间,避免了不必要的遍历和检查。
  4. 扩展性:epoll支持边缘触发(Edge Triggered)和水平触发(Level Triggered)两种工作模式。边缘触发模式只在状态变化时通知应用程序,而水平触发模式则在状态保持的情况下持续通知应用程序。这使得应用程序可以更灵活地处理事件。
  5. 内存管理:epoll使用红黑树和双链表来管理文件描述符集合,这种数据结构使得添加和删除文件描述符的操作更高效。而selectpoll则使用位图或数组来管理文件描述符集合,效率较低。
  6. **大规模并发:**由于epoll的高效性和扩展性,它更适合处理大规模并发的场景。它能够处理成千上万个文件描述符,而selectpoll在文件描述符数量较大时性能会下降。

epoll相比select和poll在效率、性能和工作模式等方面都有显著的改进,使其在高并发、大文件描述符数量的场景下具有更好的表现。因此,在实际应用中,epoll通常被作为首选的多路复用机制。

学习参考:Select、Poll、Epoll详解

7. docker用过吗?什么场景怎么用的?你认为docker里的空间和虚拟机有什么区别?

解析:

容器相关基础知识,常考题。

参考答案:

Docker是一种开源的容器化平台,它可以将应用程序及其依赖项打包成一个独立的容器,提供了一种轻量级、可移植和可扩展的软件交付解决方案。

以下是一些常见的使用场景和区别:

  1. 应用程序部署:Docker可以将应用程序及其依赖项打包成一个容器,使得应用程序在不同的环境中能够一致地运行,简化了部署过程。
  2. 微服务架构:Docker容器可以独立运行,每个容器承载一个小型的、独立的服务,使得微服务架构更加灵活和可扩展。
  3. 持续集成和持续部署:Docker容器可以与持续集成和持续部署工具集成,实现自动化的构建、测试和部署流程。

Docker空间和虚拟机的区别:

  1. 资源占用:虚拟机需要独立的操作系统和硬件资源,因此占用的资源较多。而Docker容器共享主机的操作系统内核,只需要额外的容器运行时和应用程序依赖的资源,因此占用的资源较少。
  2. 启动速度:虚拟机需要启动整个操作系统,因此启动速度较慢。而Docker容器只需要启动容器运行时和应用程序,因此启动速度较快。
  3. 隔离性:虚拟机提供了较高的隔离性,每个虚拟机都有独立的操作系统和内核。而Docker容器共享主机的操作系统内核,隔离性相对较弱,但通过Linux内核的命名空间和控制组等技术,仍然能够提供一定程度的隔离。
  4. 可移植性:虚拟机可以在不同的物理主机或虚拟化平台上运行。而Docker容器可以在任何支持Docker的主机上运行,提供了更高的可移植性。

Docker相对于虚拟机具有更轻量级、更快速的启动和更高的资源利用率,适用于快速部署和扩展应用程序的场景。虚拟机提供了更高的隔离性和可移植性,适用于需要完全隔离的环境或跨平台部署的场景。

学习参考:Docker入门,这一篇就够了,建议收藏

8. TCP和UDP的区别?

解析:

TCP 相关内容属于计算机网络必考部分,要熟练掌握。

参考答案:

  • TCP是面向连接的,UDP是无连接的
  • TCP是可靠的,UDP是不可靠的
  • TCP是面向字节流的,UDP是面向数据报文的
  • TCP只支持点对点通信,UDP支持一对一,一对多,多对多
  • TCP报文首部20个字节,UDP首部8个字节
  • TCP有拥塞控制机制,UDP没有
  • TCP协议下双方发送接受缓冲区都有,UDP并无实际意义上的发送缓冲区,但是存在接受缓冲区

学习参考:TCP与UDP的区别(超详细)

9. TCP三次握手和四次挥手的过程?三次握手为什么不能是两次?四次挥手为什么不能是三次?

解析:

TCP 相关内容属于计算机网络必考部分,要熟练掌握。

参考答案:

HTTP本身并不涉及三次握手和四次挥手的过程,这些过程实际上是TCP(传输控制协议)建立连接和断开连接时使用的机制。HTTP是建立在TCP之上的应用层协议,因此了解TCP的这些机制有助于更好地理解HTTP的工作方式。

三次握手的过程

  1. SYN(同步)阶段:客户端向服务器发送一个SYN包,并等待服务器的确认。这个SYN包中包含了客户端的初始序列号。
  2. SYN-ACK(同步-应答)阶段:服务器收到SYN包后,向客户端发送一个SYN-ACK包作为应答。这个SYN-ACK包中包含了服务器的初始序列号以及对客户端初始序列号的确认。
  3. ACK(应答)阶段:客户端收到SYN-ACK包后,向服务器发送一个ACK包作为最终的确认。这个ACK包中包含了对服务器初始序列号的确认。

为什么不能是两次

  • 防止已失效的连接请求报文段突然又传送到了服务端:客户端发出的连接请求报文段可能因为网络拥堵而在某个网络节点长时间滞留,以致延误到连接释放以后的某个时间才到达服务端。这时,服务端会误以为这是一个新的连接请求,于是又向客户端发出确认报文段,同意建立连接。如果不采用“三次握手”,那么只要服务端发出确认,新的连接就建立了。由于现在客户端并没有发出建立连接的请求,因此不会理睬服务端的确认,也不会向服务端发送数据。但服务端却认为新的运输连接已经建立,并一直等待客户端发来数据。这样,服务端就白白浪费了许多资源。采用“三次握手”的办法可以防止上述现象发生。例如上面这种情况发生时,客户端不会向服务端的确认发出确认。服务端由于收不到确认,就知道客户端并没有要求建立连接。
  • 防止已失效的连接请求报文段被服务端接收:客户端发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留后,最终到达了服务端。这本是一个早已失效的报文段。但服务端收到此失效的连接请求报文段后,就误认为是客户端再次发出的一个新的连接请求。于是就向客户端发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要服务端发出确认,连接就建立了。但由于客户端并没有发出建立连接的请求,因此不会理睬服务端的确认,也不会向服务端发送数据。但服务端却认为新的运输连接已经建立,并一直等待客户端发来数据。这样,服务端就又白白浪费了许多资源。

四次挥手的过程

  1. FIN(结束)阶段:客户端向服务器发送一个FIN包,表示客户端想要关闭连接。
  2. ACK(应答)阶段:服务器收到FIN包后,向客户端发送一个ACK包作为应答,表示已经收到客户端的关闭请求。此时,服务器仍然可以发送数据给客户端。
  3. FIN阶段:当服务器完成所有数据发送后,它也向客户端发送一个FIN包,表示服务器也想要关闭连接。
  4. ACK阶段:客户端收到服务器的FIN包后,向服务器发送一个ACK包作为最终的确认,表示客户端已经收到服务器的关闭请求。至此,连接完全关闭。

为什么不能是三次

  • 确保数据完全传输:在四次挥手中,第一次和第二次挥手确保了客户端发起关闭连接的请求,并得到服务器的确认。而第三次和第四次挥手则确保了服务器在发送完所有数据后也发起关闭连接的请求,并得到客户端的确认。这样的设计可以确保数据在双方之间完全传输,避免了数据丢失或未完全发送的情况。
  • 处理半关闭状态:TCP连接允许半关闭状态,即一方可以关闭它的发送通道,但继续接收来自另一方的数据。四次挥手能够处理这种半关闭状态,确保在双方都同意关闭连接之前,连接不会被意外中断。

学习参考:一文彻底搞懂 TCP三次握手、四次挥手过程及原理

9. HTTP3.0了解过吗?QUIC协议的底层原理是什么?

解析:

HTTP3.0 相关内容属于计算机网络常考部分,要熟练掌握。

参考答案:

HTTP/3.0是下一代HTTP协议,其最显著的特点是采用了QUIC协议作为传输层协议,取代了之前的TCP+TLS+HTTP/2.0的组合。QUIC协议的设计初衷是为了解决TCP协议在建立连接时的延迟问题,同时提供更高效、更安全的数据传输。

QUIC协议的底层原理主要包括以下几个方面:

  1. 基于UDP的传输:QUIC协议是基于UDP(用户数据报协议)的,这使得QUIC能够避免TCP协议在建立连接时的三次握手过程,从而降低了连接建立的延迟。此外,UDP的无连接特性也使得QUIC在数据传输时更加灵活和高效。
  2. 多路复用和流量控制:QUIC协议实现了类似TCP的流量控制功能,能够根据网络状况动态调整数据的发送速率,以避免网络拥塞。同时,QUIC也支持多路复用,这意味着在同一个物理连接上,可以有多个独立的逻辑数据流同时进行数据传输,从而提高了数据的传输效率。
  3. 加密和安全性:QUIC协议集成了TLS(传输层安全性协议)加密功能,使得数据传输过程中可以确保数据的机密性和完整性。这种加密功能不仅提高了数据传输的安全性,也避免了TCP+TLS组合时可能产生的握手延迟。
  4. 快速握手:由于QUIC协议是基于UDP的,因此它支持0-RTT(零往返时间)和1-RTT(一次往返时间)的快速握手功能。这意味着在客户端和服务器之间已经建立过连接的情况下,客户端可以无需再次进行完整的握手过程就能发送数据,从而进一步降低了连接的延迟。

HTTP/3.0和QUIC协议的推广和应用也面临一些挑战。例如,目前许多服务器和浏览器端对HTTP/3.0的支持还不够完善,这在一定程度上限制了HTTP/3.0的普及。此外,由于UDP协议在现有网络中的优化程度还低于TCP,因此在部署HTTP/3.0和QUIC协议时可能需要考虑网络环境的优化问题。

学习参考:QUIC/HTTP3 协议原理

10. 一个32位系统,dump结果有1G,但是用户申请512M却触发OOM了,有几种原因?

解析:

操作系统中,难度较高,属于提高题。

参考答案:

在一个32位系统中,尽管系统整体的dump结果(可能是内存转储或系统日志)有1G,但用户申请512M内存时触发OOM(Out of Memory,内存溢出)可能有以下几种原因:

  1. 内存碎片:系统中的可用内存可能已经被分割成许多小块,无法组合成足够大的连续内存块来满足512M的请求。这种情况通常发生在长时间运行且频繁进行内存分配和释放的系统中。
  2. 内核或驱动占用大量内存:内核本身或某些驱动程序可能占用了大量内存,导致用户空间可用的内存减少。即使系统整体的内存使用没有达到上限,用户空间也可能因为内核或驱动的占用而无法申请到足够的内存。
  3. 缓存和缓冲区占用:系统的缓存(如文件缓存、页面缓存等)和缓冲区可能占用了大量内存。这些内存虽然可以被回收,但在某些情况下(如内存压力较大时),回收过程可能不够及时,导致用户空间无法申请到足够的内存。
  4. 内存泄漏:系统中可能存在内存泄漏的问题,即某些进程或模块在申请内存后没有正确释放,导致内存逐渐耗尽。即使总的dump结果有1G,但可用的连续内存可能已经很少。
  5. 内存超配:某些虚拟化环境或容器技术可能会采用内存超配的策略,即允许虚拟机或容器使用的内存超过其物理内存的限制。在这种情况下,即使物理内存足够,但由于超配策略的限制,也可能触发OOM。
  6. 内存限制:系统管理员可能为用户或进程设置了内存使用限制(如通过cgroups或ulimit等工具)。即使系统整体有足够的内存,但如果用户或进程达到了其内存使用限制,也会触发OOM。
  7. 内核参数配置不当:某些内核参数(如overcommit策略)的配置可能影响到系统对内存申请的处理方式。如果配置不当,可能导致系统即使有足够的内存也拒绝用户的内存申请。

学习参考:什么是OOM,为什么会OOM及一些解决方法

更多面经直通车

原贴连接

24面经大全 文章被收录于专栏

收录各个网友分享的各个公司的面经,并给出答案。

全部评论
大佬们,研一选方向纠结,广东双非硕,嵌入式还是Java呀
点赞 回复
分享
发布于 03-16 13:24 广东

相关推荐

28 200 评论
分享
牛客网
牛客企业服务