高性能服务器编程-I/O复用

一、概念

1、作用

将获取数据的操作延后到数据到达以后。数据到达以后,有数据的文件描述符上会有一个就绪事件,服务器只需要处理就绪事件就可以。这样单进程、单线程就可以同时监听多个文件描述符。下面讨论的I/O复用方式都是单进程的。

2、linux下实现I/O复用的系统调用主要有:select、poll、epoll

二、select

1、作用

 在一段时间内,采用轮询方式监听用户感兴趣的文件描述符上的可读、可写和异常事件。

2、函数原型

#include <sys/select.h>

int select(int nfds,fd_set *read,fd_set *write,fd_set *execpt,struct timeval *timeout)

参数意义:

  nfds:最大文件描述符+1。如果监听的是3号文件描述符,那么此处的nfds就为4。

  read、write、execpt:分别存储用户感兴趣的文件描述符的可读、可写、异常事件。

    struct fd_set

    {

       long fd_set[32];

    }

    结构体总共1024位,每位监听一个文件描述符,所以最多可以监听1024个文件描述符,值为0~1023。

   

  如上图所示,监听的是3号文件描述符,服务器如何判断该文件描述符上是否有时间发生?

  fd_set[31] & 1<<3(3为3号文件描述符),即0000 & 1000==0,表示内核修改过,该文件描述符上有事件发生。如果是1000 & 1000==3,所得的结果不等于0,说明该文件描述符上没有事件发生。

  timeout:如果为NULL,则表示select一直阻塞,直到有文件描述符就绪

  函数返回值:返回值=0,表示超时

                        返回值>0,返回值的数表示就绪文件描述符的个数

                        返回值<0,select调用出错

注意:因为内核修改数据时,都是在同一个数组上修改,所以每次select之前,都必须重新设置可读、可写、异常事件

三、poll

1、作用

在指定事件内轮询一定数量的文件描述符,以测试其中是否有就绪者

2、函数原型

#include <poll.h>

int poll(struct pollfd *fds,int nfds,int timeout)

参数意义:

 struct pollfd

 {

    int fd;//文件描述符

    short events;//关注的事件类型

    short revents;//由内核填充,指定文件描述符上发生了什么事情

  } 

  nfds:数组元素个数,即数组大小

  timeout:超出时间,单位毫秒。-1表示永远阻塞,0表示立即返回

  函数返回值:返回值=0,超时

                        返回值>0,就绪文件描述符的个数

                        返回值<0,调用poll函数出错

3、select与poll的比较

(1)poll将监听的文件描述符和其关注的事件分开表示,poll不需要用三个结构体来表示不同的事件类型

(2)因为poll将用户注册的事件与内核修改的事件分开表示,所以poll不需要每次调用之前重新设置

4、部分代码

四、epoll

1、作用

epoll是Linux中特有的I/O复用函数,它在实现和使用上与select、poll有很大差异。epoll把用户关心的文件描述符上的事件放在内核里的一个事件表中,无需每次调用都要重复传入文件描述符集和事件集,所以epoll需要一个额外的文件描述符,来唯一标识内核中的内核事件表。

2、函数原型

#include <sys/epoll.h>

int epoll_create(int size);//创建一个内核事件表,返回内核表示的标识符id

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

参数意义:

  epfd:epoll_create函数的返回值,内核事件表的id

  op:操作

  event:事件类型

  struct epoll_event

  {

    int events;

    epoll_data_t data;

  }

int epoll_wait(int epfd,struct epoll_event *revents,int maxevents,int timeout);//这个函数是epoll系统调用的主要接口,它在一段超时时间内等待一组文件描述符上的事件

参数意义:

  revents:是一个记录内核就绪事件的数组

3、部分代码

五、三种IO复用的比较

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值