IO多路转接select、poll、epoll模型

I/o多路转接之select:

一、select:

1、特点:负责等
2、可以等待多个fd(read负责读取)
系统提供select函数来实现多路复用输入/输出模型
输入:用户想告诉操作系统哪个是你应该关心的读事件
输出:操作系统告诉用户你所关心的文件描述符上的事件哪些是fd已经就绪

二、select函数原型:

#include<sys/select.h>
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);

这里写图片描述

三、理解select执行过程:(理解fd_set)

fd_set长度为1字节,fd_set中的每一bit可以对应一个fd,则1字节长的fd_set最大可以对应8个fd。

用int数组来保存文件描述符

四、socket就绪条件:

1、读就绪

1)、Socket内核中接受缓冲区的字节数>=低水位标记SO_RCVLOWAT,可以无阻塞的读

2)、监听的Socket上有新的链解请求

3)、socket上有未处理的错误
4)、Socket Tcp通信中,对端关闭连接,此时对该Socket读,则返回0;

2、写就绪:

1)、Socket内核中,发送缓冲区的可用字节数》=低水位标记SO_RCVLOWAT,此时可以无阻塞的写
2)、Socket的写操作被关闭(close或者shutdown),对一个写操作被关闭的Socket进行写操作,会触发SIGPIPE信号
3)、Socket使用非阻塞connect连接成功或失败后
4)、Socket上有未读取的错误

3、异常就绪:Socket上收到带外数据。(有一个紧急指针的字段)

五、select的特点:

1)可监控的文件描述符个数取决与sizeof(fdset)的值,例:sizeof(fdset)=512,每bit表示一个文件描述符,则此服务器上最大的文件描述符是512*8=4096.
2)fd加入select监控集,再使用一个数组array保存放到select监控集中的fd
*用于再select返回后,array作为源数据和fdset进行DISSSET判断
*****Select返回后把以前加入的但并无事件发生的fd清空,每次开始select前都必须从array数组取得fd逐一加入,扫描array的同时取得fd最大值maxfid,用于select的第一个参数。

六、selec的缺点:

1)性能降低,代码难写

2)数组承载有上限(位图有大小,所存的文件描述符就有限)

3)开销大

4)输入输出函数混合在一起必须依赖一个第三方数组

I/O多路转接之poll:

一、函数接口:

#include<poll.h>
int poll(struct pollfd *fds,nfds_t nfds,int timeout);
//pollfd 结构
struct pollfd{
     int fd;                     /*file descriptor*/
     short events;       /*requested events*/
     short revents;     /*returned events*/
     };

这里写图片描述

2、events和revents的取值

events:所关心的fd是什么

revents:所关心的fd哪些已经就绪

3、返回结果:

1)返回值小于0,表示出错
2)返回值等于0,表示poll函数等待超时;
3)返回值大于0,表示poll由于监听的文件描述符就绪而返回。

二、socket就绪条件:

同select

三、poll的优点:

不同于select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现

1)polled结构包含了要发生的event和发生过的event,不再使用select”参数-值”的传递方式,

接口比select更方便

2)poll并没有最大数量限制

(但是数量过大后性能也是会下降)

四、poll的缺点

poll监听的文件描述符数目增多时:

1)性能下降

(同时连接的大量客户端一时刻只有少数处于就绪状态)

2)麻烦

(每次调用poll都要把大量的pollfd结构从用户态拷到内核中)
(poll返回后,需要轮询polled来获取就绪的描述符)

I/o多路转接之epoll

一、epoll初识:是为处理大批量句柄而做了改进的poll

二、epoll工作原理:

这里写图片描述

三、epoll的三个调用:

1、epoll_create

int epoll_create(int size);
创建一个epoll的句柄。
1)linux2.6.8之后,size参数是被忽略的
2 )用完之后,必须调用close()关闭。

2、epoll_ctl(操控红黑树)

    int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);

这里写图片描述

3、epoll_wait(操控就绪队列)

int epoll_wait(int epfd,struct epoll epoll_event * events,int maxevents,int timeout);

这里写图片描述

总结:

epoll使用三部曲:

1)调用epoll_create创建一个epoll句柄
2)调用epoll_ctl,将要监控的文件描述符进行注册
3)调用epoll_wait,等待文件描述符就绪

四、epoll的优点

1)文件描述符无上限
2)基于事件的就绪通知方式。(函数的读和写分开来执行)(一旦就绪,内核采用callback的回调机制,迅速激活这个文件描述符,不会影响性能)
3)维护就绪队列:当fd就绪,就被放入就绪队列,调用epoll_wait获取fd(O(1))
4)内存映射机制错误(建立过程中传了缓冲区,完成了从内核到用户数据的拷贝)

五、epoll工作方式:默认(LT)

水平触发(LT)&&边缘触发(ET)

LT:可靠,不会丢失数据
ET:更高效 有->无 才通知
少->多

LT:

1)既可用也可不用非阻塞

2)检测到socket事件时,不立刻处理,或只处理一部分
3)读1k数据,缓冲区还剩1k,在第二次调用epoll_wait时,仍然立刻返回并通知socket读事件就绪
4)data被处理完,epoll_wait才不会立刻返回

ET:

1)遇到socket事件就绪,必须立刻处理
2)读1k数据,缓冲区还剩1k,在第二次调用epoll_wait时,不会再返回
3)fd就绪后,只有一次处理机会
4)ET比LT性能更高(epoll_wait返回的次数少了很多)。

5)只支持非阻塞的读写:数据就绪只会通知一次,ET:数据就绪,需一直read,直到出错或完成为止。

六、epol使用场景

对于多连接,且多连接中只有一部分连接比较活跃时,比较适合用epoll。(QQ,微信)

七、epoll中的惊群问题

本来连接很多活跃度低,但是在某一时刻,活跃度骤升,就会导致epoll服务器压力过大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值