2.操作系统常见面试问题3
2.53 Linux中 epoll 和 select 的作用与使用方法,简述 epoll 和 select 的区别,epoll 为什么高效?
-
作用:
select
和epoll
用于多路复用I/O,在单个线程中管理多个文件描述符,提升并发处理能力。 -
使用方法:
- select:通过设置文件描述符集,调用后检查哪些文件描述符有I/O事件。
- epoll:通过
epoll_create
创建实例,epoll_ctl
添加或修改文件描述符,epoll_wait
等待事件发生。
-
区别:
- 调用效率:
select
每次调用都要遍历文件描述符集,效率随连接数增加而下降;epoll
基于事件驱动,只通知有事件的文件描述符,适合大规模并发。 - 文件描述符上限:
select
有文件描述符上限(一般1024),epoll
几乎无限制。
- 调用效率:
-
epoll高效原因:
epoll
将活跃文件描述符直接保存在内核,减少用户和内核空间拷贝,事件触发机制避免了无效轮询。
总结表格
特性 | select | epoll |
---|---|---|
调用效率 | 每次遍历文件描述符,随连接数增加效率下降 | 基于事件驱动,只处理活跃的文件描述符 |
文件描述符上限 | 有文件描述符上限(1024或2048) | 无显著限制 |
适用场景 | 少量连接或简单任务 | 大量并发连接或高频事件通知 |
2.54 说说多路 IO 复用技术有哪些,区别是什么?
精简回答:
-
多路 I/O 复用技术:在 Linux 中,多路 I/O 复用技术包括**
select
、poll
、epoll
**,用于在一个线程中监控多个文件描述符的状态,以提高并发能力。 -
区别:
- select:遍历全部文件描述符,有描述符上限限制,效率随连接数增加下降。
- poll:与
select
类似,但没有文件描述符上限;依然需遍历全部文件描述符。 - epoll:事件驱动机制,只处理有事件的文件描述符,适合高并发场景。
总结表格
特性 | select | poll | epoll |
---|---|---|---|
文件描述符上限 | 一般为1024或2048 | 无限制 | 无显著限制 |
触发方式 | 水平触发 | 水平触发 | 水平触发或边沿触发 |
效率 | 随连接数增加而下降 | 随连接数增加而下降 | 高效,连接数增加不影响性能 |
适用场景 | 少量连接的简单任务 | 中等数量连接的任务 | 大量并发连接或频繁事件触发 |
全面回答:
-
select:
- 特点:
select
使用一个固定大小的位掩码来表示文件描述符集合,每次调用需重新设置集合并遍历整个集合。它的文件描述符数量有限制(一般1024或2048)。 - 触发方式:水平触发(level-triggered),需要不断轮询以查看哪些文件描述符有事件。
- 特点:
-
poll:
- 特点:
poll
和select
相似,但使用链表存储文件描述符集合,因此可以监控更多文件描述符。它没有文件描述符数量的限制。 - 触发方式:水平触发,每次调用都要遍历整个集合,不适合大规模连接。
- 特点:
-
epoll:
- 特点:
epoll
是基于事件驱动的模型,只有文件描述符有事件发生时才通知,避免了遍历全部文件描述符的开销。它使用事件列表保存活跃的文件描述符,适合高并发场景。 - 触发方式:支持水平触发(level-triggered)和边沿触发(edge-triggered),边沿触发模式在高并发下性能更优。
- 特点:
区别总结
- 性能:
select
和poll
随着连接数增加,效率会显著下降,而epoll
在大规模并发连接中表现更佳。 - 触发机制:
select
和poll
都为水平触发,epoll
支持边沿触发,适合高频事件场景。
2.55 简述 socket 中select ,epoll 的使用场景和区别,epoll 水平触发与边缘触发的区别?
精简回答:
-
使用场景:
- select:适合少量连接或较简单的 I/O 任务,如小型应用的并发处理。
- epoll:适合大量并发连接的高性能应用,如 Web 服务器。
-
select 和 epoll 的区别:
- 文件描述符管理:
select
有文件描述符数量限制,而epoll
几乎无限制。 - 触发机制:
select
每次调用都需遍历所有文件描述符,epoll
采用事件驱动,只处理有事件的文件描述符,效率更高。
- 文件描述符管理:
-
epoll 水平触发和边缘触发区别:
- 水平触发(LT):当有数据可读时,系统会不断通知,适合流式处理。
- 边缘触发(ET):只在状态变化时通知,适合高性能场景,但需要一次性处理完数据。
总结表格
特性 | select | epoll (水平触发) | epoll (边缘触发) |
---|---|---|---|
使用场景 | 少量连接或简单 I/O 任务 | 高并发场景,流式或频繁 I/O 任务 | 高并发、高性能场景,瞬时大量数据处理 |
触发方式 | 水平触发 | 水平触发 | 边缘触发 |
事件通知频率 | 重复通知,只要数据可读就通知 | 重复通知 | 状态变化才通知,一次性处理 |
适用复杂度 | 中小型应用 | 大规模并发 | 高频并发场景,性能更优 |
全面回答:
-
使用场景:
- select:适合小型服务器或客户端应用。因为
select
每次调用都需要遍历所有文件描述符,效率随连接数增大而降低,不适合大规模并发应用。 - epoll:适用于高并发、大规模 I/O 操作的场景。
epoll
采用事件驱动机制,支持大量文件描述符,适合需要频繁 I/O 事件的高性能服务器,如 Web 服务器、实时消息系统等。
- select:适合小型服务器或客户端应用。因为
-
select 和 epoll 的区别:
- 性能差异:
select
每次调用都需重新设置文件描述符集合,耗时且效率低。epoll
只需管理活跃的文件描述符,且不需要重复拷贝文件描述符集合,性能显著提升。 - 文件描述符上限:
select
有文件描述符上限(一般为1024或2048),不适合高并发场景;而epoll
没有此限制,能处理大量并发连接。 - 内核通知机制:
select
的实现为水平触发机制,而epoll
支持水平触发和边缘触发两种模式,灵活性更高。
- 性能差异:
-
epoll 水平触发和边缘触发的区别:
- 水平触发(Level Triggered, LT):文件描述符有未处理数据时,会不断通知。适合逐步处理数据的场景,编程复杂度较低,但在高并发场景中通知频繁。
- 边缘触发(Edge Triggered, ET):只在状态变化(如从不可读到可读)时通知,不会反复提醒。适合一次性处理大批数据,减少重复通知,提高性能。需要开发者手动确保一次性将数据读完,编程复杂度更高。
2.56 说说 Reactor 、Proactor 模式。
精简回答:
-
Reactor模式:一种同步非阻塞I/O模型,处理I/O事件的分发。应用程序只负责响应事件通知(如可读、可写),并在事件触发时自行执行I/O操作。
-
Proactor模式:一种异步I/O模型,处理I/O事件的完成。应用程序只需提交I/O请求,由操作系统自动完成I/O操作,并在操作结束后通知应用程序处理结果。
总结表格
特性 | Reactor模式 | Proactor模式 |
---|---|---|
I/O模型 | 同步非阻塞I/O | 异步I/O |
I/O操作的执行方 | 应用程序执行 I/O 操作 | 操作系统或库执行 I/O 操作 |
应用程序任务 | 响应事件并执行具体I/O | 等待完成通知并处理结果 |
适用场景 | 高并发I/O,适合多任务分发 | 对异步支持较好平台,如 Windows |
全面回答:
-
Reactor模式:
- 工作原理:Reactor模式使用一个事件循环来等待并分发事件。当I/O事件(如数据到达、可以发送)发生时,事件循环通知应用程序,应用程序再执行具体的I/O操作。这种模式中的I/O操作由应用程序同步执行。
- 特点:
- 同步非阻塞:Reactor只负责通知事件的到来,不负责I/O操作的完成。
- 事件驱动:应用程序只需关注事件的响应,适合高并发场景。
- 适用场景:常用于Linux服务器和高并发系统,如HTTP服务器,数据库系统。
-
Proactor模式:
- 工作原理:Proactor模式将I/O操作委托给操作系统或I/O库,应用程序只需提交I/O请求并等待操作完成的通知。操作系统完成I/O操作后,应用程序收到完成事件,处理数据即可。
- 特点:
- 异步I/O:操作系统负责完成I/O操作,应用程序只处理完成后的事件。
- 回调机制:Proactor采用回调方式处理I/O完成事件,应用程序代码较为简洁。
- 适用场景:常用于对异步支持较好的操作系统,如Windows中的异步I/O模型,适合高性能和低延迟的场景。
区别
- I/O操作执行方:Reactor需要应用程序执行具体I/O操作,而Proactor则将I/O操作的完成交由系统负责。
- 异步特性:Reactor使用非阻塞I/O,操作同步;Proactor采用异步I/O,操作异步更具效率。
2.57 简述同步与异步的区别,阻塞与非阻塞的区别?
-
同步 vs. 异步:
- 同步:在同步模式中,调用方在调用一个函数或发出一个任务时,必须等待该任务完成才能继续执行。比如读取一个文件时,必须等待文件读取完成。
- 异步:在异步模式中,调用方发出任务后无需等待任务完成,即可继续执行其他操作,任务完成后通过回调函数、通知、事件等方式告知调用方。异步适合长时间任务或需要并发执行的场景。
-
阻塞 vs. 非阻塞:
- 阻塞:调用方在发出调用后,当前线程被挂起,直到任务完成。阻塞常用于简单的同步任务,但在高并发场景下效率低下。
- 非阻塞:调用方发出调用后即刻返回,不管任务是否完成。非阻塞的I/O调用不会挂起调用方线程,适合高并发场景中并发执行多任务。
-
区别总结:
- 同步/异步决定是否需要等待任务完成;阻塞/非阻塞决定调用后是否挂起调用方线程。
2.58 BIO 、 NIO 有什么区别?
精简回答:
-
BIO(Blocking I/O,阻塞I/O):每次I/O操作(读写)都阻塞在操作完成前,适合少量连接或小规模并发应用,编程简单但效率低。
-
NIO(Non-blocking I/O,非阻塞I/O):I/O操作可以立即返回,即使未完成也不会阻塞。适合高并发、大规模连接场景,通常结合多路复用技术,如
select
、poll
、epoll
。
总结表格
特性 | BIO(阻塞I/O) | NIO(非阻塞I/O) |
---|---|---|
I/O 模式 | 阻塞 | 非阻塞 |
执行方式 | 调用方等待任务完成 | 调用方立即返回,可执行其他任务 |
适用场景 | 少量连接、简单任务 | 高并发、大规模连接 |
实现复杂度 | 简单 | 较高,通常结合多路复用 |
2.59 请介绍一下五种IO模型
精简回答:
五种常见的I/O模型如下:
- 阻塞I/O(Blocking I/O):应用程序调用阻塞,直到I/O完成,常用于简单应用。
- 非阻塞I/O(Non-blocking I/O):应用程序调用立即返回,无需等待I/O完成,适合高并发场景。
- I/O多路复用(I/O Multiplexing):通过
select
、poll
、epoll
等系统调用同时监控多个I/O,适合处理多连接的场景。 - 信号驱动I/O(Signal-driven I/O):利用信号机制通知应用I/O事件的到来,减少轮询的开销。
- 异步I/O(Asynchronous I/O):应用程序发出I/O请求后立即返回,由系统完成I/O操作并通知应用程序,适合高性能场景。
总结表格
I/O模型 | 描述 | 适用场景 |
---|---|---|
阻塞I/O | 调用被阻塞,直到I/O完成 | 小规模应用、简单I/O操作 |
非阻塞I/O | 调用立即返回,需轮询检查 | 高并发、低延迟的系统 |
I/O多路复用 | 使用select 、poll 等监控多I/O | 多连接场景,如Web服务器 |
信号驱动I/O | 利用信号通知I/O事件到来 | 低延迟场景,有信号支持的系统 |
异步I/O | I/O由系统完成,完成后通知应用 | 高性能应用,如数据库、Web服务器 |
全面回答:
-
阻塞I/O(Blocking I/O):
- 原理:调用I/O函数后,线程会被阻塞,直到数据传输完成。此期间线程无法执行其他操作。
- 优缺点:编程简单,但并发时性能差。
- 适用场景:适合低并发、小规模的应用程序。
-
非阻塞I/O(Non-blocking I/O):
- 原理:I/O操作调用后会立即返回,线程需不断轮询检查I/O状态。返回时可能未完成任务,需反复检查或处理。
- 优缺点:支持高并发,但轮询开销较大。
- 适用场景:适合并发较高、响应速度要求高的应用场景。
-
I/O多路复用(I/O Multiplexing):
- 原理:通过
select
、poll
、epoll
等系统调用,等待多个文件描述符的事件(如可读、可写)。当一个或多个描述符状态变化时返回,并执行I/O操作。 - 优缺点:高效处理多连接,但调用复杂。
- 适用场景:适合高并发连接场景,如聊天室和Web服务器。
- 原理:通过
-
信号驱动I/O(Signal-driven I/O):
- 原理:在I/O事件上启用信号驱动,I/O事件到来时,操作系统发送信号通知应用程序,减少轮询需求。
- 优缺点:可减少CPU轮询开销,但需额外处理信号机制。
- 适用场景:适合对延迟敏感的场景,有信号支持的系统环境。
-
异步I/O(Asynchronous I/O):
- 原理:应用程序提交I/O请求后立即返回,操作系统在后台完成I/O操作,完成后通知应用程序处理结果。实现完全的异步处理。
- 优缺点:效率高,但实现复杂,依赖操作系统支持。
- 适用场景:适合高性能应用,如数据库系统和大型Web服务器。
2.60 请说一下socket 网络编程中客户端和服务端用到哪些函数?
精简回答:
在 socket 网络编程中,客户端和服务端的核心函数如下:
客户端
- socket():创建套接字。
- connect():连接到服务器。
- send()/recv():发送和接收数据。
- close():关闭连接。
服务端
- socket():创建套接字。
- bind():将套接字绑定到本地地址和端口。
- listen():监听连接请求。
- accept():接受客户端连接。
- send()/recv():发送和接收数据。
- close():关闭连接。
全面回答:
在 C++ 的 socket 网络编程中,客户端和服务端一般按照如下步骤调用相关函数完成通信:
1. 客户端端函数流程
- socket():创建一个套接字,指定通信协议(如TCP)。
- connect():将套接字连接到远程服务器地址和端口。
- send()/recv():发送和接收数据,
send()
用于向服务端发送数据,recv()
用于接收服务端返回的数据。 - close():完成通信后关闭连接。
2. 服务端函数流程
- socket():创建一个套接字,指定通信协议。
- bind():将套接字绑定到本地地址和端口,使其可监听指定端口的连接请求。
- listen():将套接字设为监听模式,指定最大连接数。
- accept():等待并接受客户端连接,返回新的套接字以进行通信。
- send()/recv():
send()
向客户端发送数据,recv()
接收客户端发送的数据。 - close():通信结束后关闭连接。
示例流程代码
客户端
int client_socket = socket(AF_INET, SOCK_STREAM, 0);
connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
send(client_socket, "Hello Server", strlen("Hello Server"), 0);
recv(client_socket, buffer, sizeof(buffer), 0);
close(client_socket);
服务端
int server_socket = socket(AF_INET, SOCK_STREAM, 0);
bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server_socket, 5);
int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_size);
send(client_socket, "Hello Client", strlen("Hello Client"), 0);
recv(client_socket, buffer, sizeof(buffer), 0);
close(client_socket);
close(server_socket);
这两个端代码展示了如何在C++ socket网络编程中完成基本的客户端和服务端通信。
2.61 简述网络七层参考模型,每一层的作用?
精简回答:
网络七层参考模型是用于理解计算机网络通信的结构模型,分为以下七层:
- 物理层:负责物理传输介质上的比特流传输。
- 数据链路层:负责数据帧的传输和错误检测。
- 网络层:负责数据包的路由和转发。
- 传输层:提供端到端的通信,保证数据传输的可靠性。
- 会话层:管理会话的建立、维护与终止。
- 表示层:处理数据的编码、加密、解密、压缩等。
- 应用层:为应用提供网络服务,如HTTP、FTP、SMTP等。
总结表格
层级 | 名称 | 作用 |
---|---|---|
第7层 | 应用层 | 提供应用程序网络服务,如HTTP、FTP等 |
第6层 | 表示层 | 数据编码、解码、加密、压缩 |
第5层 | 会话层 | 管理会话、控制会话的建立与终止 |
第4层 | 传输层 | 端到端通信、可靠数据传输 |
第3层 | 网络层 | 数据包路由和转发 |
第2层 | 数据链路层 | 数据帧的传输、错误检测 |
第1层 | 物理层 | 物理传输比特流 |
全面回答:
OSI(开放系统互联)七层模型,也称为网络七层参考模型,是由国际标准化组织(ISO)提出的,目的是为了规范网络通信中的各个过程,并且方便不同设备和系统之间的通信。每一层都有其独特的作用,具体如下:
-
物理层:
- 物理层是最底层,负责传输原始的比特流。它定义了网络硬件、传输介质(如电缆、光纤)以及信号的电气特性。
- 例如:以太网、Wi-Fi、光纤等。
-
数据链路层:
- 数据链路层负责数据帧的传输,包括数据的打包、帧的校验、差错检测与纠正。它确保数据在物理链路上可靠传输。
- 例如:以太网协议、MAC地址。
-
网络层:
- 网络层负责数据包的路由和转发。它决定数据如何在网络中传输到目标地址(通常是IP地址)。网络层提供不同子网或网络之间的通信。
- 例如:IP协议、路由协议。
-
传输层:
- 传输层负责建立、管理和终止端到端的通信会话。它确保数据从源到目标的可靠传输,并进行流量控制、错误校验、重传等操作。
- 例如:TCP、UDP。
-
会话层:
- 会话层用于建立、管理和终止会话(即通信过程)。它确保两台计算机之间的会话可以持久,并能在需要时恢复中断的会话。
- 例如:RPC(远程过程调用)。
-
表示层:
- 表示层负责数据的表示、编码、加密和解密等功能。它确保传输的内容能够被接收方正确理解,并且对数据进行压缩和加密以增加安全性。
- 例如:JPEG、MPEG、SSL/TLS(加密)。
-
应用层:
- 应用层为应用程序提供网络服务,处理具体的应用数据交换。它定义了网络服务的接口和协议,通常与用户交互。
- 例如:HTTP(Web浏览)、FTP(文件传输)、SMTP(邮件发送)等。
通过这七层的分层结构,可以清晰地看到不同网络协议的功能和作用,有助于系统地理解计算机网络通信的各个环节。