IO复用三种方式
简介
IO复用技术,简单来说就是同时监听多个描述符。在没有用到IO复用以前,只能是一个线程或一个
线程去监听,服务端同时有多个连接的时候,需要创建多个线程或者进程。而且,并不是所有的连
接是一直在传输这数据,可能只是连接后啥都没干,如果这样,进程就啥都没干。
现在有了IO复用技术,只有描述符就绪的时候才去处理,这样就很方便了。
IO复用的使用大概是这样:
设置要监听的描述符以及需要监听的事件
↓
监听事件,一直阻塞直到有描述符就绪
↓
遍历所有就绪的描述符,并进行相应处理
IO复用有三种方式,分别是select, poll, epoll
select
select函数原型
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);
参数详解:
nfds:nfds参数指定的是被监听的文件描述符的总数,一般设置成最大的描述符加上1,因为描述
符是从0开始的。
readfds:需要监听读事件的描述符集
writefds:需要监听写事件的描述符集
exceptfds:需要监听异常事件的描述符集
timeout:设置超时时间,如果传递的是NULL,则select会一直阻塞
一般的使用步骤:
1 设置FD_SET集合,如果要同时监听多种事件,则需要使用多个描述符集合
2 调用select,select会通过更改描述集,只留下准备好的描述符,所以需要在调用前保留一份
3 同时描述符需要在数组中存储一份,这个通过遍历数组和FD_ISSET来判断是否准备好,若准备好则去执行相关任务
缺点:
select 最大支持的描述符有限一般是1024。
同时select内部的操作是等待描述符集合,必然需要进入到内核态,所以,每次需要把描述符集合
从用户空间拷贝到内核空间,这样是特别消耗资源的,同时select这种方式,只保留准备好的描述符
这样,使用特别不方便,每次还需要对数组进行遍历来判断描述符是否在准备好的集合当中。
poll
poll相对于select的优点就是解决了描述符的限制问题,但是性能并不好。poll也是需要通过遍历
的方式来判断描述符的准备状态,当描述符较多时,则就尴尬了。
函数原型:
int poll(struct pollfd *fds, nfd_t nfds, int timeout);
struct pollfd
{
int fd; //文件描述符
short events; //注册的事件
short revents; //实际发生的事件
}
参数详解:
fds:需要监听的数组,数组里的每个结构体都设置好描述符和需要注册的事件,如果有多个,使用或('|')操作符
nfds:数组的长度
timeout:指定超时值,单位是毫秒
常用的宏:
POLLIN:数据(包括普通数据和优先数据)可读
POLLOUT:数据(包括普通数据和优先数据)可写
epoll
epoll 相比select和poll不同,epoll将监听的描述符集存放在内核区,免去了select和poll每次调用
都需要将描述符集从用户空间拷贝到内核空间的消耗。同时epoll的对于已经准备好的描述符处理比较方便。
还增加了一些新的特性,比如ET和LT两种触发模式,
epoll提供了三个函数:
int epoll_create(int size);
epoll_create用来创建一个描述符,指向内核创建的描述符集。之后的操作都通过描述符来操作。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd:传入的是指向描述符集的描述符
op:有三个宏:
EPOLL_CTL_ADD: 添加fd上的注册事件
EPOLL_CTL_MOD: 修改fd上的注册事件
EPOLL_CTL_DEL: 删除fd上的注册事件
fd:需要操作的描述符
event:
struct epoll_event
{
__uint32_t events; //epoll事件
epoll_data_t data; //用户数据
}
typedef union epoll_data_t
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
函数详解:
返回值:返回准备好的描述符的个数
epfd:指向描述符集的描述符
events:这里是作为函数传出使用,epoll_wait之后会设置这个数组,之后再遍历这个数组即可
maxevents:指定最多监听的描述符的个数
timeout:超时时间,和poll相同。
epoll有两种触发模式,一种是LT(条件触发)一种ET(边沿触发)
LT条件触发:
当满足某个条件,就会触发,如果没有去处理,会一直去触发
LT是默认的触发方式
ET边沿触发:
当满足某个条件之后触发一次,如果未处理,就不管了。
在设置触发事件的时候或上 EPOLLET
那么问题来了?
如果之后还有数据到来,还会触发吗?
如果会,那么之前未处理的数据还在吗,会丢弃吗?
如果之后还有新的数据来,依然会触发,同时之前缓冲的数据可以一块读出来。
IO复用三种方式的更多相关文章
- IO多路复用三种方式select/poll/epoll
select多并发socket例子: #_*_coding:utf-8_*_ __author__ = 'Alex Li' import select import socket import sys ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- Java基础知识强化之IO流笔记62:三种方式实现键盘录入
1. 三种方式实现键盘录入 System.in 标准输入流.是从键盘获取数据的 键盘录入数据三种方式: A:main方法的args接收参数. java HelloWorld hello w ...
- 监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile
大家在学习entityframework的时候,都知道那linq写的叫一个爽,再也不用区分不同RDMS的sql版本差异了,但是呢,高效率带来了差灵活性,我们 无法控制sql的生成策略,所以必须不要让自 ...
- 0036 Java学习笔记-多线程-创建线程的三种方式
创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...
- android中解析文件的三种方式
android中解析文件的三种方式 好久没有动手写点东西了,最近在研究android的相关技术,现在就android中解析文件的三种方式做以下总结.其主要有:SAX(Simple API fo ...
- Java Class类以及获取Class实例的三种方式
T - 由此 Class 对象建模的类的类型.例如,String.class 的类型是Class<String>.如果将被建模的类未知,则使用Class<?>. publi ...
- 三种方式上传文件-Java
前言:负责,因为该项目他(jetty嵌入式开始SpringMvc)实现文件上传的必要性,并拥有java文件上传这一块还没有被曝光.并 Http 更多晦涩协议.因此,这种渐进的方式来学习和实践上载文件的 ...
- 使用Net.Mail、CDO组件、JMail组件三种方式发送邮件
原文:使用Net.Mail.CDO组件.JMail组件三种方式发送邮件 一.使用Net.Mail 需要服务器认证,大部分服务器端口为25. { MailMessage mailMsg = mailMs ...
随机推荐
- 为WebDriver 设置proxy(IE设置代理)
IE driver String PROXY = "http://proxy:8083"; org.openqa.selenium.Proxy proxy = new org.op ...
- jquery返回滚动条顶部
var $view = $('html,body'),$backTop = $('#backTop'), $backTop.on('click',function(){ $view.animate({ ...
- 简单粗暴将sqlserver表以及数据迁移到oracle
1.利用sqlserver工具查询出表中所有数据,全选,右键 -连同标题一起复制. 2.将数据保存到excel文件,数据 时间类型(yyyy--MM--dd HH:mm:ss)最好处理一下,需要将id ...
- Jquery 实现点击tab切换页签
1.我将这个封装城了插件代码如下,你可以独立到一个js文件,然后页面引用下这个js文件: (function ($) { $.fn.extend({ qmTabs: function () { var ...
- myeclipse(2015)中创建简单的Maven项目的步骤(用于生成可执行jar文件)------》myeclipse2015
利用MyEclipse的引导,可以很方便的创建简单的.用于生成可执行jar文件的Maven项目: 1.New -> Project... 选择 Maven Project, 点击Next > ...
- kettle系列-2.kettle源码结构分析
kettle是一个开源产品,产品本身设计是很优秀的,代码应该是很多开源爱好者用业余时间贡献的,代码整体结构还是比较容易理解的,但具体到每一个控件内部就因人而异了,感觉还是挺复杂的,肯定别人考虑得比较全 ...
- 【转载】CentOS服务器配置VPN详解
转载来自: https://bbs.aliyun.com/read/162297.html http://www.wanghailin.cn/centos-7-vpn/ 操作系统:CentOS 6.3 ...
- 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】
一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...
- python IOError: [Errno 0] Error
Windows系统下,此异常在以'a+'模式打开文件,读文件,再写入过程中出现.其原因在于读写交替过程中必须要有fflush, fseek, fsetpos, rewind这类操作,不然python就 ...
- OpenCv全景图像拼接
http://my.oschina.net/xiaot99/blog/226589 http://blog.csdn.net/chenjiazhou12/article/details/2282548 ...