当前位置: 首页 > news >正文

文件I/O与I/O多路复用

1.文件表

进程打开一个文件,会与三个表发生关联,分别是:文件描述符表、文件表、索引结点表。
在这里插入图片描述

在 Linux/Unix 系统中,Socket 确实被抽象为一种特殊的文件。这是 Unix “一切皆文件”(Everything is a File)设计哲学的体现。

在 /proc/pid/fd/ 中可见。

为什么fork之后,要把不用的文件关掉
防止资源泄漏,每个打开的文件描述符都会占用系统资源。系统对单个进程和整个系统能打开的文件描述符数量都有限制。

C 标准库(stdio)中 fread 和 fwrite 的缓冲机制。这是理解高性能 I/O 操作的关键之一。
一、为什么需要缓冲?
核心目的:减少系统调用的次数,极大提升 I/O 效率。

stdin 和 stdout 如果指向终端(交互式设备),通常是行缓冲;如果被重定向到文件,则通常变为全缓冲。

2.多路复用

1.select 的作用

1.select 的核心作用是:允许一个进程(或线程)同时监视多个文件描述符(File Descriptor, FD),等待其中一个或多个 FD 变得“可读”、“可写”或“发生异常”,然后通知程序进行相应的读写操作。

简单来说,它解决了“一个服务端程序如何同时高效地处理多个客户端连接”的问题,而不需要为每个连接都创建一个进程或线程。

2.为什么要用 select?—— 解决的核心问题
在 select/poll/epoll 这类技术出现之前,处理多个网络连接的常规方法是:

多进程模型:accept 一个连接就 fork 一个子进程来处理。问题:进程创建、销毁、上下文切换开销巨大,资源占用高,难以应对成千上万的连接(这就是著名的 C10K problem)。
多线程模型:accept 一个连接就创建一个线程。问题:虽然比进程轻量,但大量线程的上下文切换开销依然很大,而且编程中线程同步非常复杂。
非阻塞忙轮询(Busy-polling):将 socket 设为非阻塞,然后在一个循环里依次调用 recv 检查每个连接。问题:CPU 资源被极大浪费,因为大部分时间都是在做无用的检查。
select 的出现就是为了克服上述模型的缺点:

资源高效:一个线程就能管理成百上千个网络连接,大大降低了系统资源消耗。
避免忙等待:在没有事件发生时,select 会阻塞(睡眠),让出 CPU 资源。只有当事件发生(或有信号中断)时,它才会被唤醒,从而高效利用 CPU。
统一事件管理:可以同时等待多种类型的 I/O 事件(可读、可写、异常),使得程序能够统一处理所有连接的 I/O 活动。

3.核心步骤对应代码
设置集合:FD_ZERO, FD_SET 初始化并填充需要监视的 fd(如监听 socket 和所有客户端 socket)。
阻塞等待:调用 select(nfds, &readfds, NULL, NULL, NULL)。
检查结果:select 返回后,使用 FD_ISSET 遍历所有 fd,判断哪些 fd 上有事件发生。
处理事件:
如果是监听 socket 可读,说明有新连接,调用 accept。
如果是客户端 socket 可读,说明有数据到来,调用 recv。

2.poll 相对于select的真正优势

既然都需要轮询,那 poll 的优势在哪里?它解决的是 select 的其他设计缺陷:

问题 select poll
连接数限制 有,受 FD_SETSIZE (通常1024) 限制 无硬性限制,仅受系统内存限制
内核反馈机制 使用“传入-传出”参数,每次调用后原始集合被破坏,需要重置。 使用独立的 events(输入)和revents(输出)字段,无需重置。
处理异常 需要额外的 exceptfds 集合。 可以通过 events 字段直接设置

3.epoll

解决了这个轮询问题,epoll 的工作方式是“事件就绪通知”:

你告诉内核要监视哪些 FD(通过 epoll_ctl)。
当事件就绪时,epoll_wait 调用返回,它只给你一个装满就绪事件的数组,这个数组的大小恰好就是就绪 FD 的数量。
你直接处理这个数组即可,时间复杂度是 O(就绪的fd数量),而不是 O(总共监视的fd数量)。

epoll_create1: 创建一个 epoll 实例,返回一个文件描述符(epfd),用于管理所有待监视的 FD。
epoll_ctl: 向 epoll 实例(epfd)添加、修改或删除要监视的 FD 及其感兴趣的事件(EPOLLIN, EPOLLOUT 等)。这个操作只需执行一次,而不是每次循环都传递整个集合。
epoll_wait: 等待事件发生。它只返回那些已经就绪的 FD 信息(一个 events 数组),数量就是就绪的 FD 数。应用程序无需遍历所有监视的 FD,直接处理这些就绪的事件即可。这是 O(1) 的复杂度。

http://www.xdnf.cn/news/1475029.html

相关文章:

  • 外置flash提示音打包脚本
  • 版本发布流程手册:Release分支规范与Bug分级标准全解析
  • [C++刷怪笼]:搜索二叉树--便利的查找工具
  • 【数据库相关】TxSQL新增数据库节点步骤
  • Nmap使用手册
  • 第08章 聚合函数
  • 数据结构:查找
  • Matplotlib 动态显示详解:技术深度与创新思考
  • 【3D算法技术】blender中,在曲面上如何进行贴图?
  • 少儿舞蹈小程序(9)校区信息展示
  • MAZANOKE与cpolar:打造安全可控的照片云端管理系统
  • 01-线上问题处理-树形结构拼接
  • 数据库原理及应用_数据库管理和保护_第5章数据库的安全性_理论部分
  • [光学原理与应用-436]:晶体光学 - 各向同性与各向异性是描述材料物理性质随方向变化特性
  • STAR-CCM+|雷诺数回顾
  • windows11 安装charm成功
  • U-Boot 多 CPU 执行状态引导
  • 【LeetCode热题100道笔记】验证二叉搜索树
  • 深入浅出迁移学习:从理论到实践
  • 基于YOLO8的汽车碰撞事故检测系统【数据集+源码+文章】
  • 10.LED+TIR透镜优化——lighttools入门笔记
  • SpringBootWeb 篇-深入了解 ThreadLocal 存在内存泄漏问题
  • 记一次uniapp微信小程序开发scss变量失效的问题
  • 5-10数组元素添加和删除(数组基础操作)
  • 【Python自动化】 21.1 Pandas 读取 Excel 文件的完整指南
  • 从挑西瓜到树回归:用生活智慧理解机器学习算法
  • 【Python】数据可视化之分布图
  • 51单片机---硬件学习(电子琴、主从应答模式、modbus模型、DS18B20传感器显示温度)
  • AI驱动的软件测试:革命性的自动化、缺陷检测与实验优化
  • Java并发机制的底层实现原理