文件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.mzph.cn/bicheng/52390.shtml

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

相关文章

C++观察者模式Observer

组件协作 –(都是晚绑定的&#xff09; ----观察者模式 为某些对象建立一种通知依赖的关系&#xff0c; 只要这个对象状态发生改变&#xff0c;观察者对象都能得到通知。 但是依赖关系要松耦合&#xff0c;不要太依赖。 eg&#xff1a;做一个文件分割器&#xff0c;需要一个…

css实现水滴效果图

效果图&#xff1a; <template><div style"width: 100%;height:500px;padding:20px;"><div class"water"></div></div> </template> <script> export default {data() {return {};},watch: {},created() {},me…

B/S架构和C/S架构的区别

B/S架构、C/S架构区别 1. B/S架构 1.1 什么是B/S架构 B/S架构的全称为Browser/Server&#xff0c;即浏览器/服务器结构。Browser指的是Web浏览器&#xff0c;极少数事务逻辑在前端实现&#xff0c;但主要事务逻辑在服务器端实现。B/S架构的系统无须特别安装&#xff0c;只需要…

动态内存管理-经典笔试题

目录 题目一&#xff1a; 题目二&#xff1a; 题目三&#xff1a; 题目四&#xff1a; 题目一&#xff1a; 结果&#xff1a;程序崩溃 原因&#xff1a; 1、函数是传值调用&#xff0c;出了函数p不存在&#xff0c;str未改变&#xff0c;依旧为空指针&#xff0c;运行时发…

【CTF Web】CTFShow 版本控制泄露源码2 Writeup(目录扫描+.svn泄漏)

版本控制泄露源码2 10 版本控制很重要&#xff0c;但不要部署到生产环境更重要。 解法 用 dirsearch 扫描。 dirsearch -u https://8d22223d-dc2c-419c-b82d-a1d781eda427.challenge.ctf.show/找到 .svn 仓库。 访问&#xff1a; https://8d22223d-dc2c-419c-b82d-a1d781eda…

ubuntu安装minio

# 下载MinIO的可执行文件 curl -O https://dl.min.io/server/minio/release/linux-amd64/minio # 添加执行权限 chmod x minio # 运行MinIO (需要先创建存储数据和存储存储桶的目录) nohup ./minio server /home/lighthouse/minioDir/data /home/lighthouse/minioDir/bucke…

修复线上问题,又造成了个Bug

项目场景 这是一位朋友给我分享的实际线上问题&#xff0c;看似简单却害了项目再次造出一个bug来。 场景&#xff1a;线上环境中&#xff0c;需要查询某某业务数据&#xff0c;条件是状态&#xff0c;之前产品只要求查两个状态的&#xff0c;但现在让他再多查一个状态的。 自…

时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention

时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention 文章目录 前言时序预测|基于贝叶斯BO-卷积-双向门控单元-注意力机制的单变量时间序列预测模型BO-CNN-BiGRU-Attention 一、BO-CNN-BiGRU-Attention模型1. 贝叶斯优化&#…

Go Convey测试框架入门(go convey gomonkey)

Go Convey测试框架入门 介绍 GoConvey是一款针对Golang的测试框架&#xff0c;可以管理和运行测试用例&#xff0c;同时提供了丰富的断言函数&#xff0c;并支持很多 Web 界面特性。 Golang虽然自带了单元测试功能&#xff0c;并且在GoConvey框架诞生之前也出现了许多第三方测…

OSPF路由原理详解与关键点

目录 一. OSPF简介: 二. OSPF原理描述: 三. OSPF的核心内容: 四. OSPF的邻居关系和邻接 五. LSA在各区域中传播的支持情况 一. OSPF简介: 开放式最短路径优先OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&…

技术债务已接管经济

“技术债务”一词通常指软件开发过程中的捷径或次优方法。它表现为设计不良的代码、缺乏文档和过时的组件。虽然正确编写的代码和文档是永恒的&#xff0c;但组件和方法却不是。随着时间的推移&#xff0c;软件及其组件可能会成为技术债务。自 40 年前的 20 世纪 80 年代软件行…

【嵌入式开发之网络编程】TCP端口和UDP端口

目录 网络端口的定义及作用 运输层的作用 运输层的两个主要协议 用户数据报协议UDP (User Datagram Protocol) 传输控制协议TCP (Transmission Control Protocol) 运输层的端口及分类 按照端口号分类 按照协议类型分类 BSD端口 网络端口的定义及作用 在网络技术中…

《通义千问AI落地—下》:WebSocket详解

一、前言 文本源自 微博客 且已获授权,请尊重版权。 《通义千问AI落地——下篇》如约而至。Websocket在这一类引用中,起到前后端通信的作用。因此,本文将介绍websocket在这类应用场景下的配置、使用、注意事项以及ws连接升级为wss连接等;如下图,本站已经使用了wss连接…

iphone异常问题常用修复方法

作为智能手机的领军者&#xff0c;iPhone凭借其卓越的性能和稳定的系统赢得了全球用户的青睐。然而&#xff0c;就像任何电子设备一样&#xff0c;iPhone在使用过程中也难免会遇到各种异常问题&#xff0c;如卡顿、无法充电、应用闪退等。这些问题虽然令人头疼&#xff0c;但大…

防范小程序隐私合规风险,筑牢用户信任防线

随着国内APP软件生态的成熟&#xff0c;依托于头部APP的小程序逐渐成为零售、娱乐、出行等行业必选的获客渠道之一。较低的开发成本和成熟的用户营销功能&#xff0c;令小程序的数量在过去几年呈指数级增长。截止2023年&#xff0c;头部APP内集成的小程序总量已超千万。然而&am…

C语言 之 memcpy函数的内存重叠问题 及解决该问题的思路

文章目录 函数原型&#xff1a;例子&#xff1a; 解决方式整体思路如下&#xff1a; 内存重叠问题主要是使用函数memcpy的时候会发生的 函数原型&#xff1a; void * memcpy ( void * destination, const void * source, size_t num);这个函数能够在source指向的空间中拷贝nu…

嘉立创EDA个人学习笔记2(设计流程及绘制元件)

前言 本篇文章属于嘉立创EDA的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 【教程】零基础入门PCB设计-国一学长带你学立创EDA专业版 全程保姆…

黑神话:悟空-配置推荐

显卡推荐&#xff08;按类别整理&#xff09; 1. GTX 10系列、GTX 16系列&#xff1a; 如果希望体验光线追踪&#xff0c;建议根据预算升级到RTX 40系列显卡。对于1080p分辨率&#xff0c;至少需要RTX 4060才能流畅运行。 2. RTX 20系列&#xff1a; RTX 2060、RTX 2070&#…

-Wl,-rpath= 编译器链接器指定动态库路径 与 LD_LIBRARY_PATH

实例先行&#xff0c; 1&#xff0c;情景 三互相依赖的小项目&#xff1a; &#xff08;1&#xff09;libbottom.so&#xff0c;无特别依赖&#xff0c;除系统文件 &#xff08;2&#xff09;libtop.so&#xff0c;依赖libbottom.so &#xff08;3&#xff09;app 可执行程…

buuctf [HDCTF2019]Maze

前言&#xff1a;做题笔记。 常规 下载 解压 查壳 脱壳后用32IDA Pro打开。 得&#xff0c;迷宫类型的题目。(字符串有说。) 咳&#xff0c;此前思路对半分不行了。。。 合理猜测步数为&#xff1a;14。 那可以看看7 * 10的迷宫类型。(手动猜测的时候去取倍数如&#xff1a;0 2…