I/O多路复用-EPOLL探索
I/O多路复用就是通过一种机制,可以监视多个描述符,一旦某个IO能够读写,通知程序进行相应的读写操作。
I/O多路复用的场合
1、当客户处理多个描述字时(通常是交互式输入和网络套接字),必须使用I/O复用
2、如果一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用
3、如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用
Linux 下I/O多路复用的方式
SELECT、POLL、EPOLL
对比SELECT、POLL、EPOLL
SELECT缺点
每次调用select,都需要把fd集合从用户态拷贝到内核态,开销和fd的数量成正比
每次调用select都需要在内核遍历传递进来的所有fd,开销和fd的数量成正比
select支持的文件描述符数量太少,32位1024个,64位2048个
POLL缺点
poll和select本质相同,使用链表存储文件描述符,没有最大连接数的限制
下图是select、poll、kqueue(FreeBSD平台)、epoll四种方式连接数和时间关系图
上图可以看出,随着fd数量的增大,select、poll的时间消耗非常大,kqueue和epoll基本上没有变化
EPOLL优点
1、它所支持的FD上限是最大可以打开文件的数目,在1GB内存的机器上大约是10万左 右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
2、IO 效率不随FD数目增加而线性下降
3、epoll不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd,而不是全部遍历。
下面是一个场景,一个服务端Server.py,多个客户端订阅,服务端不断的生成消息,客户端订阅后服务端会不断的把消息发送给客户端:
Server:
#!/usr/bin/env python
# -*- coding:utf-8 -*- __author__ = 'Andy'
import socket, select, traceback, time
import threading
import Queue gen = Queue.Queue()
connections = {}
requests = {}
responses = {} def run():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('127.0.0.1', 8080))
serversocket.listen(5)
serversocket.setblocking(0)
epoll = select.epoll() # 创建一个epoll对象
epoll.register(serversocket.fileno(), select.EPOLLIN) # 给新建的serversocket.fileno注册一个读event try:
count = 0
while True:
events = epoll.poll() # 激活的fileno举手
count += 1
for fileno, event in events:
if fileno == serversocket.fileno(): # 当激活的fileno是新建的,给该fileno注册一个读event
connection, address = serversocket.accept()
connection.setblocking(0)
epoll.register(connection.fileno(), select.EPOLLIN)
connections[connection.fileno()] = connection
requests[connection.fileno()] = b''
responses[connection.fileno()] = b""
print "new conn.fileno is %s" % connection.fileno()
elif event & select.EPOLLIN: # 如果fileno是读event,接收发送来消息,并修改该fileno为写event,下次循环时写数据
print "read event is happing"
requests[fileno] += connections[fileno].recv(1024)
epoll.modify(fileno, select.EPOLLOUT)
print('-' * 40 + '\n' + requests[fileno].decode()[:-2])
elif event & select.EPOLLOUT: # 如果fileno是写事件,写完后正常的为挂起
if responses[fileno]:
byteswritten = connections[fileno].send(responses[fileno])
responses[fileno] = responses[fileno][byteswritten:]
if len(responses[fileno]) == 0:
epoll.modify(fileno, select.EPOLLOUT) # 需要向订阅者一直发消息,这里发完后仍为写event
print "change event to write"
elif event & select.EPOLLHUP:
epoll.unregister(fileno)
connections[fileno].close()
del connections[fileno]
print "event is HUP ===%s" % fileno
pass
except Exception, err:
print traceback.print_exc()
finally:
epoll.unregister(serversocket.fileno())
epoll.close()
serversocket.close()
print "finally" def create_data():
count = 1
while True:
count += 1
res = "Message-%s" % count
gen.put_nowait(res) # 把消息放入队列
time.sleep(0.5) def update_message():
while True:
message = gen.get()
for res in responses: # 遍历所有的活跃用户,更新消息
responses[res] = message
time.sleep(0.05) if __name__ == "__main__":
p = threading.Thread(target=create_data) # 开个线程向队列里放数据
p1 = threading.Thread(target=update_message) # 从队列中取出数据
p.start()
p1.start()
run()
p.join()
p1.join()
Client:
#!/usr/bin/env python
# -*- coding:utf-8 -*- __author__ = 'Andy'
import socket,time
def sim_client(name,i):
connFd = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
connFd.connect(("127.0.0.1", 8080))
connFd.send("Process-%s start subscibe\n\n" % name)
while True:
try:
readData = connFd.recv(1024)
if readData:
print "*"*40 + "\n" + readData.decode()
except:
time.sleep(0.2) if __name__=="__main__":
sim_client("progressage",1)
来看一下输出结果
服务端接受订阅的消息:
客户端订阅服务端的消息
才疏学浅,目前只研究了EPOLL的水平触发,还有边缘触发需要去探索
作者:Andy
出处:http://www.cnblogs.com/onepiece-andy/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
I/O多路复用-EPOLL探索的更多相关文章
- 非阻塞套接字编程, IO多路复用(epoll)
非阻塞套接字编程: server端 import socket server = socket.socket() server.setblocking(False) server.bind(('', ...
- I/O多路复用——epoll函数
1 select的低效率 select/poll函数效率比较低,主要有以下两个原因: (1)调用select函数后需要对所有文件描述符进行循环查找 (2)每次调用select函数时都需要向该函数传递监 ...
- IO多路复用epoll
0 why: 问题来源 0.1 网络编程流程 //创建socket int s = socket(AF_INET, SOCK_STREAM, 0); //绑定IP地址和端口号port bind(s, ...
- IO多路复用之epoll总结
1.基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本.相对于select和poll来说,epoll更加灵活,没有描述符限制.epoll使用一个文件描述符管理多个描述 ...
- 多路复用(select、epoll)实现tcp服务
-------------------------------多路复用的服务器(select)------------------------------- 网络通信被Unix系统抽象为文件的读写,通 ...
- unix网络编程——I/O多路复用之epoll
1. 基本概念 当程序进行IO时,如果数据尚未准备好,那么IO将处于阻塞状态.当某个进程有多个打开的文件,比如socket,那么其后的所有准备好读写的文件将受到阻塞的影响而不能操作.不借助线程,单一进 ...
- IO多路复用之epoll
1.基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本.相对于select和poll来说,epoll更加灵活,没有描述符限制.epoll使用一个文件描述符管理多个描述 ...
- 【python】-- IO多路复用(select、poll、epoll)介绍及实现
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
- IO多路复用(select、poll、epoll)介绍及select、epoll的实现
IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...
随机推荐
- mongodb复杂条件查询 (or与and)
分类专栏: mongodb 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/tjbsl/ ...
- RookeyFrame模块初始化
上一篇讲了下线上创建模块,这一次讲下线下创建的模块如何初始化,实体类的创建可参考Demo中的客户主数据模块 首先讲下model类创建中的约定: 1.所有数据模型继承BaseEntity 2.需要绑定枚 ...
- linux系统下安装配置Jenkins
准备java 环境 安装java sdk yum -y install java 验证是否安装成功 java -version 下载安装jenkins 官网:https://wiki.jenkins- ...
- [TCP/IP] ping traceroute和TTL
1.Time To Live是生存时间的意思,就是说这个ping的数据包能在网络上存在多少时间.当我们对网络上的主机进行ping操作的时候,我们本地机器会发出一个数据包,数据包经过一定数量的路由器传送 ...
- 磁盘I/O 监控 iostat
iostat -cdxm 2 5 dm-4 如果没有这个命令,需要安装sysstat 包. Usage: iostat [ options ] [ <interval> [ <cou ...
- MacOS上传文件到windows ftp时链接文件不见了
最近打包遇到了一个问题,打包完MAC的sdk包后,得到的是一个framework的文件夹,我们需要将这个framework传到ftp服务器上,另外,还要把这个文件夹下的Release文件夹里的文件替换 ...
- 201871010123-吴丽丽 《面向对象程序设计(Java)》第十四周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- 201871010106-丁宣元 《面向对象程序设计(java)》第十三周学习总结
201871010106-丁宣元 <面向对象程序设计(java)>第十三周学习总结 正文开头: 项目 内容 这个作业属于哪个课程 https://home.cnblogs.com/u/nw ...
- 解决IIS7、IIS7.5 应用程序池回收假死的方法
最近iis网站一直假死状态,都懵了,查看程序有没有关闭数据库,反复捣鼓,还一直测试是否是程序应用池自动回收问题依然没有效果.经过老师提醒,找到了解决办法,在此做个笔记! 原因在于:应用程序池超时配置被 ...
- 微信小程序 - 结构目录 | 配置介绍
结构目录 小程序框架提供了自己的视图层描述语言 WXML 和 WXSS,以及 JavaScript,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑. 一.小程序文件结构和传 ...