文件IO和多路复用IO

目录

前言

一、文件 I/O

1.基本文件 I/O 操作

1.1打开文件

1.2读取文件内容 (read)

1.3写入文件 (write)

1.4关闭文件 (close)

2.文件指针

二、多路复用 I/O

1.常用的多路复用 I/O 模型

1.1select

1.2poll

1.3epoll

2.使用 select、poll 和 epoll 进行简单的 I/O 监控

3.select、poll 和 epoll 三种 I/O 多路复用模型的对比


前言

  • 文件 I/O 是程序与外部数据交互的基础,可以通过读取和写入文件实现数据持久化。文件 I/O 的操作相对简单,适用于普通的数据读写场景。
  • 多路复用 I/O 则是一种高级 I/O 操作模式,能够有效地处理多个文件描述符的 I/O 事件,广泛应用于网络编程中,特别是在高并发服务器中发挥着重要作用。常用的多路复用 I/O 模型包括 selectpollepoll

一、文件 I/O

文件 I/O(Input/Output,输入/输出)指的是计算机程序与文件进行交互的过程,这些文件通常存储在磁盘上。文件 I/O 是程序与外部数据交互的基础,能够实现数据的存储、读取和处理。

1.基本文件 I/O 操作

1.1打开文件

  • 在进行文件操作之前,需要先打开文件。open 函数用于打开文件,并返回一个文件对象,供后续操作使用。
  • 语法:file_object = open(file_name, mode)
  • 常用模式:
    • "r": 读取(默认)
    • "w": 写入(会覆盖原有文件)
    • "a": 追加(在文件末尾追加内容)
    • "b": 二进制模式(如 "rb", "wb" 等)
    • "+": 更新模式(读写都可以,如 "r+", "w+"

1.2读取文件内容 (read)

  • 打开文件后,可以使用 read()readline()readlines() 方法读取文件内容。
  • read(size):读取文件中 size 个字节内容,如果不指定 size,则读取整个文件。
  • readline():按行读取文件,返回文件中的一行。
  • readlines():返回文件中的所有行,结果是一个包含每行内容的列表。
with open("example.txt", "r") as file:content = file.read()print(content)

1.3写入文件 (write)

  • 使用 write() 方法将字符串写入文件中。如果文件是以 "w" 模式打开的,写入时会覆盖文件内容。
  • 如果想逐行写入,可以使用 writelines() 方法,这个方法接受一个字符串列表,每个字符串将作为一行写入文件。
with open("example.txt", "w") as file:file.write("Hello, World!\n")file.writelines(["Line 1\n", "Line 2\n"])

1.4关闭文件 (close)

操作完成后,应当使用 close() 关闭文件,以释放系统资源。不过,使用 with 语句可以自动关闭文件。

file = open("example.txt", "r")
# 执行操作
file.close()  # 关闭文件

2.文件指针

  • 文件指针是指示文件中当前读写位置的标记。
  • tell():获取文件指针当前位置。
  • seek(offset, from_what):移动文件指针到指定位置。offset 表示偏移量,from_what 表示参考点(0: 文件开头, 1: 当前位置, 2: 文件结尾)。

二、多路复用 I/O

多路复用 I/O 是一种高级 I/O 操作模式,允许一个进程同时监听多个文件描述符(如文件、网络连接等),并根据事件发生情况进行相应处理。它的优势在于避免了传统阻塞 I/O 操作的等待时间,提升了并发处理的效率。

1.常用的多路复用 I/O 模型

1.1select

  • select 是一种跨平台的 I/O 多路复用接口,能够监控一组文件描述符(包括套接字),当其中的一个或多个描述符准备好进行 I/O 操作时,select 返回并指示哪些描述符可以进行操作。
  • 它的基本思想是通过单个系统调用等待多个文件描述符中的任何一个变得可读、可写或有错误发生。
import select
import socket# 创建 socket 对象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen(5)inputs = [sock]
while True:readable, writable, exceptional = select.select(inputs, [], [])for s in readable:if s is sock:conn, addr = s.accept()inputs.append(conn)else:data = s.recv(1024)if data:print("Received:", data.decode())else:inputs.remove(s)s.close()

1.2poll

  • pollselect 的改进版本,克服了 select 的一些限制(如文件描述符数量限制)。
  • poll 使用一个 poll 对象来监控多个文件描述符。它的行为和 select 类似,但性能更好,特别是在监控大量描述符时。
import select
import socketsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen(5)poller = select.poll()
poller.register(sock, select.POLLIN)fd_to_socket = {sock.fileno(): sock}
while True:events = poller.poll()for fd, flag in events:s = fd_to_socket[fd]if flag & select.POLLIN:if s is sock:conn, addr = s.accept()poller.register(conn, select.POLLIN)fd_to_socket[conn.fileno()] = connelse:data = s.recv(1024)if data:print("Received:", data.decode())else:poller.unregister(fd)s.close()del fd_to_socket[fd]

1.3epoll

  • epoll 是 Linux 提供的一种高效的多路复用 I/O 模型,适用于大量并发连接场景。相比 selectpollepoll 更加高效,因为它采用了事件通知机制,避免了轮询的开销。
  • epoll 可以分为水平触发(Level-Triggered,LT)和边缘触发(Edge-Triggered,ET)两种模式,ET 模式更加高效,但编程更加复杂。
import select
import socketsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen(5)epoll = select.epoll()
epoll.register(sock.fileno(), select.EPOLLIN)fd_to_socket = {sock.fileno(): sock}
while True:events = epoll.poll()for fd, event in events:s = fd_to_socket[fd]if event & select.EPOLLIN:if s is sock:conn, addr = s.accept()epoll.register(conn.fileno(), select.EPOLLIN)fd_to_socket[conn.fileno()] = connelse:data = s.recv(1024)if data:print("Received:", data.decode())else:epoll.unregister(fd)s.close()del fd_to_socket[fd]

2.使用 selectpollepoll 进行简单的 I/O 监控

import select
import socket
import sysdef create_server_socket():server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_socket.bind(('localhost', 8080))server_socket.listen(5)return server_socketdef handle_select(server_socket):inputs = [server_socket]while True:readable, writable, exceptional = select.select(inputs, [], [])for s in readable:if s is server_socket:conn, addr = s.accept()inputs.append(conn)else:data = s.recv(1024)if data:s.send(data)else:inputs.remove(s)s.close()def handle_poll(server_socket):poller = select.poll()poller.register(server_socket, select.POLLIN)fd_to_socket = {server_socket.fileno(): server_socket}while True:events = poller.poll()for fd, flag in events:s = fd_to_socket[fd]if flag & select.POLLIN:if s is server_socket:conn, addr = s.accept()poller.register(conn.fileno(), select.POLLIN)fd_to_socket[conn.fileno()] = connelse:data = s.recv(1024)if data:s.send(data)else:poller.unregister(fd)s.close()del fd_to_socket[fd]def handle_epoll(server_socket):epoll = select.epoll()epoll.register(server_socket.fileno(), select.EPOLLIN)fd_to_socket = {server_socket.fileno(): server_socket}while True:events = epoll.poll()for fd, event in events:s = fd_to_socket[fd]if event & select.EPOLLIN:if s is server_socket:conn, addr = s.accept()epoll.register(conn.fileno(), select.EPOLLIN)fd_to_socket[conn.fileno()] = connelse:data = s.recv(1024)if data:s.send(data)else:epoll.unregister(fd)s.close()del fd_to_socket[fd]if __name__ == "__main__":if len(sys.argv) != 2:print("Usage: python3 server.py <select|poll|epoll>")sys.exit(1)mode = sys.argv[1]server_socket = create_server_socket()if mode == "select":handle_select(server_socket)elif mode == "poll":handle_poll(server_socket)elif mode == "epoll":handle_epoll(server_socket)else:print("Invalid mode. Use 'select', 'poll', or 'epoll'.")sys.exit(1)

3.selectpollepoll 三种 I/O 多路复用模型的对比

  • select 适用于小规模并发应用,跨平台支持广泛,但在处理大量文件描述符时性能较差。
  • poll 解决了 select 的文件描述符限制问题,适合中小规模并发连接,但在性能上不如 epoll
  • epoll 是处理大规模并发连接的最佳选择,具有出色的扩展性和性能,但仅在 Linux 系统上可用,并且编程复杂度较高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408030.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件测试最全面试题,了解一下

一、前言 近期有不少同学&#xff0c;朋友问我什么是软件测试&#xff0c;它是干什么的&#xff0c;我适不适合做、这行发展前景、工资怎么样等等等…在这里我把问题总结一下&#xff0c;整理一篇文章出来。 我也看过很多贴吧、论坛&#xff0c;在入行之前对这块都是迷茫的&a…

数据结构----栈

一丶概念 只能在一端进行插入和删除操作的线性表&#xff08;又称为堆栈&#xff09;&#xff0c;进行插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底 二丶特点 先进后出 FILO first in last out 后进先出 LIFO last in first out 三丶顺序栈 逻辑结构&…

Nginx: 配置项之http模块connection和request的用法以及limit_conn和limit_req模块

connection和request connection 就是一个连接, TCP连接 客户端和服务器想要进行通信的话&#xff0c;有很多种方式比如说, TCP的形式或者是UDP形式的通常很多应用都是建立在这个TCP之上的所以, 客户端和服务器通信&#xff0c;使用了TCP协议的话&#xff0c;必然涉及建立TCP连…

Java JNA调用C函数常见问题及解决方法

目录 1 undefined symbol&#xff1a;xxx2 Java映射C数组乱码3 Java使用String接收不到C函数返回的char*4 Unable to load DLL xxx.dll5 java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序6 无效的ELF头7 Structure array elements must use contiguous memory8 j…

msvcp120.dll丢失是怎么回事?几种靠谱修复msvcp120.dll的方法

在使用基于Windows的计算机进行日常工作或娱乐时&#xff0c;您可能会遇到一个错误消息&#xff1a;“无法启动此程序&#xff0c;因为计算机中丢失msvcp120.dll。”这样的提示通常在尝试启动某些程序或游戏时弹出&#xff0c;导致应用无法正常运行。这个问题通常与系统中的某个…

CSS3页面布局-三栏-固定宽度布局

布局的基本概念 多栏布局三种基本实现方案&#xff1a;固定宽度&#xff0c;流动&#xff0c;弹性。 固定宽度布局&#xff1a;大小不会随用户调整浏览器窗口大小。 一版960-1100,960常见&#xff0c;可以被3,4,5,6,8,10,12,16整除。 流动布局&#xff1a;大小会随用户调整…

数据结构——链式二叉树的实现与分治编程思维(c语言实现)

目录 前言&#xff1a; 1.前置说明 2.链式二叉树的遍历 2.1 前序&#xff0c;中序及后续遍历 2.2 前序遍历实现 2.3 中序遍历实现 2.4 后续遍历实现 3.结点个数以及高度等 3.1 结点个数 3.2 结点高度 3.3 叶子结点的个数 前言&#xff1a; 在之前的学习中&…

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤 多级缓存本地缓存分布式缓存 分层过滤 多级缓存 多级缓存在秒杀系统中是非常重要的一个技术点&#xff0c;是应对秒杀场景瞬时高并发读请求的一种有效手段。通过在数据库前面加入多个缓存层&#xff0c;达到过滤掉大多数读请…

优惠券秒杀项目

一、添加优惠券的同时&#xff0c;将优惠券信息&#xff0c;以及用户列表放到redis中 Override Transactional public void addSeckillVoucher(Voucher voucher) {// 保存优惠券save(voucher);// 保存秒杀信息SeckillVoucher seckillVoucher new SeckillVoucher();seckillVou…

easyexcel--多sheet页导入导出

多sheet页导出 核心代码就是下图里面的&#xff0c;使用EasyExcel.writeSheet创建一个sheet,然后用excelWriter写入就行了&#xff0c;很简单 GetMapping("downloadMultiSheet")public void downloadMultiSheet(HttpServletResponse response) throws IOException {…

【Qt】输入类控件QDateTimeEdit

目录 输入类控件QDateTimeEdit 例子&#xff1a;实现日期计算器 输入类控件QDateTimeEdit QDate Edit作为日期的微调框 QTime Edit作为时间的微调框 QDateTimeEdit作为时间日期的微调框 下面主要讲解QDateTimeEdit&#xff1a; 核心属性 属性说明 dateTime 时间⽇期的值.…

【Hot100】LeetCode—101. 对称二叉树

目录 1- 思路借助队列 2- 实现⭐101. 对称二叉树——题解思路 3- ACM 实现 原题连接&#xff1a;101. 对称二叉树 1- 思路 借助队列 1- 创建队列&#xff1a;Queue<TreeNode> queue&#xff0c;初始化加入 root.left 和 root.right2- 判断逻辑&#xff1a;while(!queu…

软件开发者的首选:最佳Bug测试工具Top 10

本篇文章介绍了以下软件bug测试管理工具&#xff1a;PingCode、Worktile、Test360、禅道、码云Gitee、优云测试、Jira、GitHub、Axosoft、Bugzilla。 在开发过程中&#xff0c;Bug的管理往往是最让人头疼的问题之一。小问题积累起来不仅会拖延项目进度&#xff0c;还可能影响到…

如何优雅处理异步组件加载:Vue 3 的 Suspense 特性

在日常开发中&#xff0c;我们可能会遇到网络不佳或内容加载时间较长的情况。如果当前页面没有任何内容提示&#xff0c;用户的体验非常糟糕&#xff0c;可能会反复刷新以便加载成功。因此&#xff0c;我们需要给用户提供一个加载中的效果&#xff0c;告知用户“我在努力加载中…

基于单片机的人体健康监测系统的设计

本设计以STM32F103C8T6单片机作为主控&#xff0c;通过MAX30102采集心率、血氧值&#xff0c;通过MSP20血压采集模块检测血压值&#xff0c;通过MLX90614红外体温采集模块检测体温值。OLED屏可以显示以上检测的信息&#xff0c;并可以通过蓝牙模块将信息发送给手机APP。当检测值…

利用VirtualBox安装CentOS系统

博主这次用VirtualBox虚拟机安装CentOS系统。无论是大小型项目都是要发布到云主机上面&#xff0c;必然要用到Linux系统&#xff0c;有的人的本地电脑硬件配置不高&#xff0c;没有办法运行数据库集群&#xff0c;所以只能借助云主机。毕竟云主机也是Linux系统&#xff0c;大家…

大数据-92 Spark 集群 SparkRDD 原理 Standalone详解 ShuffleV1V2详解 RDD编程优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

OZON什么产品好卖丨OZON婴儿用具产品

Top1 摇铃 Деревянная стойка тренажер Монтессори для мобилей и игрушек для новорожденных / развивающая дуга 商品id&#xff1a;1557614414 月销量&#xff1a;707 OZON婴儿用具…

Leetcode-day31-01背包问题

46. 携带研究材料 1.dp数组代表的是什么&#xff1f; 这里的dp数组是一个二维数组&#xff0c;dp[i][j]是从前i个物品中任选放入容量j内的最大价值。 2.递推公式。 不放物品i&#xff1a;由dp[i - 1][j]推出&#xff0c;即背包容量为j&#xff0c;里面不放物品i的最大价值&am…

uniapp检测手机是否打开定位权限Vue3-直接复制粘贴

安卓示例&#xff1a; 苹果示例&#xff1a; 代码实现&#xff08;vue3写法&#xff09;&#xff1a; const checkGPS ()>{console.log(开始监听GPS状态);let system uni.getSystemInfoSync(); // 获取系统信息if (system.platform android) { // 判断平台var context …