I/O复用
来源:互联网 发布:数据库导入excel 编辑:程序博客网 时间:2024/05/28 16:24
http://blog.sina.com.cn/s/blog_5f4344bf0100cklt.html
总的来说,I/O 处理的模型有5 种。http://www.360doc.com/content/12/0426/15/507289_206688004.shtml# ,http://blog.chinaunix.net/uid-24780853-id-2578681.html
· 阻塞 I/O模型:在这种模型下,若所调用的I/O 函数没有完成相关的功能就会使进程
挂起,直到相关数据到才会出错返回。如常见对管道设备、终端设备和网络设备进行读写时
经常会出现这种情况。
· 非阻塞模型:在这种模型下,当请求的I/O 操作不能完成时,则不让进程睡眠,
而且返回一个错误。非阻塞I/O 使用户可以调用不会永远阻塞的I/O 操作,如open、write
和read。如果该操作不能完成,则会立即出错返回,且表示该I/O 如果该操作继续执行
就会阻塞。
· I/O多路转接模型:在这种模型下,如果请求的I/O操作阻塞,且它不是真正阻塞I/O,
而是让其中的一个函数等待,在这期间,I/O 还能进行其他操作。如本节要介绍的select函数
和poll函数,就是属于这种模型。
· 信号驱动 I/O 模型:在这种模型下,通过安装一个信号处理程序,系统可以自动
捕获特定信号的到来,从而启动I/O。这是由内核通知用户何时可以启动一个I/O 操作
决定的。
· 异步 I/O模型:在这种模型下,当一个描述符已准备好,可以启动I/O 时,进程会通
知内核。现在,并不是所有的系统都支持这种模型。
一。select(不需要设置监听的文件阻塞与否,但要注意非阻塞的可写)
#include <sys/types.h>
#include <sys/times.h>#include <sys/select.h>
int select(nfds, readfds, writefds, exceptfds, timeout)
int nfds;
fd_set *readfds, *writefds, *exceptfds;
struct timeval *timeout;
a 文件描述符就绪条件-socket可读
1.socket内核接收缓冲区大于等于低水位标记SO_RCVLOWAT,此时可以无阻塞的读,读操作返回字节数大于0
2.socket通信对方关闭连接,此时读改socket返回0
3.监听socket上有新连接请求
4.socket上有未处理的错误,此时我们可以用getsockopt来去读和清除该错误
b. socket可写的就绪条件
1.socket内核发送缓存区可以字节大于等于低水位标记SO_SENLOWAT.
2.socket的写操作关闭,此时执行写操作触发SIGPIPE信号
3.使用非阻塞connect连接成功或者失败(超时)之后
4.socket上有未处理的错误,此时可以读取和清除该错误
c .socket文件就绪条件---文件异常:socket上有带外数据
http://www.2cto.com/kf/201301/180982.html
使用非阻塞 connect 需要注意的问是:http://www.cnblogs.com/yuxingfirst/archive/2013/03/08/2950281.html
1. connect返回0, connect 建立连接成功。
2. 返回不等于0,只有errno==EINROGRESS才表示连接还在进行,否则出错
Posix 定义了两条与 select 和 非阻塞 connect 相关的规定:
1)连接成功建立时,socket 描述字变为可写。(连接建立时,写缓冲区空闲,所以可写)
2)连接建立失败时,socket 描述字既可读又可写。 (由于有未决的错误,从而可读又可写)
如果只可写,说明连接成功。
若描述符既可读又可写,分为两种情况:http://www.cnblogs.com/yuxingfirst/archive/2013/03/08/2950281.html
第一种情况是socket连接出现错误
第二种情况是connect连接成功,socket读缓冲区得到了远程主机发送的数据。需要通过connect连接后返回给errno的值来进行判定,或者通过调用 getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len)来读取并清除socket上的错误,错误码errno等于0表明成功,否则失败;
如何判断呢:用select,poll等监听可写事件,当函数返回后调用getsockopt函数,这里存在一个可移植性问题,非阻塞的socket可能导致connect始终失败;select对处于EINPROGRESS状态下的socket可能不起作用;getsockopt返回值不一致-1,或者0 。
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(sockfd,&writefds);
timeout.tv_sec = 1;timeout.tv_usec = 0;ret=select(sockfd+1,NULL,&writefds,NULL,&timeout);
if(ret<=0)
return -1;//select超时或者出错
if( !FD_ISSET(sockfd,&writefds) )
{
return -1;//sockfd上没有可写事件
}
int error=0;
if (getsockopt(c_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { cout << "getsockopt error." << endl; return -1; }
if(error!=0){
cout<<"connection failed"<<end1;
return -1;
}
/*成功*/ cout << "success << endl;
二。epoll函数
1.默认是LT模型(不处理下次还会触发提醒),ET(触发事件通知后必须立即处理完)需要手动设置,同时因为要立即处理完,所以像读数据就得循环读取,直到全部读取完毕,读取完毕后还不能阻塞了程序,所以还要使用非阻塞的文件描述符
int setnonblocking(int fd)
{
int old=fcntl(fd,F_GETFL);
int new=old|O_NONBLOCK;
fcntl(fd,F_SETFL,new);
return old;
}
epoll_event event;
event.data.fd=fd;
event.events=EPOOLIN|EPOLLET;//监听可读,并设置et
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event)
setnonblocking(fd);//非阻塞
2.EPOLLONESHOT事件:避免一个socket上的某次业务因频繁通信而多次触发事件(ET模式时事件也可能被多次触发)。特别是用多线程处理时,若是多次触发事件,就会造成多个线程处理同一个socket的问题。epooloneshot使得最多触发一个可读、可写或者异常事件,且最多触发一次,除非用epoll_ctl重置
event.events=EPOOLIN|EPOLLET|EPOOLONESHOT;//监听可读,并设置et,EPOOLONESHOT
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event)
当断定这次业务处理完成后,应该重置,以便epoll_wait 还能捕获提醒某事件
event.events=EPOOLIN|EPOLLET|EPOOLONESHOT;//监听可读,并设置et,EPOOLONESHOT
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&event)
select和poll采用轮询的方式,epoll采用回调的方式,当活动连接多的时候,回调函数频繁触发,效率就未必比select和Poll好了,所以epoll适用于连接数据量多,但活动连接少的情况。
- I/O模型以及I/O复用
- epoll I/O复用
- I/O复用
- I/O 复用
- Linux I/O复用
- I/O复用-epoll
- I/O复用
- I/O复用
- I/O复用
- I/O复用poll
- I/O复用epoll
- I/O复用--《APUE1》
- I/O复用
- I/O复用
- I/O复用
- I/O复用
- I/O复用------select
- I/O复用------poll
- 安卓模拟器Genymotion安装使用教程详解
- DataGridView添加一行
- ip斜杠表示法
- Fractal
- Linux MySql 启用InnoDB
- I/O复用
- ubuntu下编译适合ndk的x264(arm和x86)
- java线程同步
- MySQL5日期类型DATETIME和TIMESTAMP相关问题详解
- fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 终极解决方案
- UVA 437 The Tower of Babylon
- 刘鹏计算广告学1:广告的基本知识(一)
- iOS 远程推送(Push Notification)实现
- VC++学习心得(六)