select、poll、epoll系统调用及ET与LT模式

select、pool 、epoll剖析:I/O复用能使系统同时监听多个文件描述符

读事件   就绪(缓冲区有数据)   客户端发数据了缓冲区才有数据。

写事件    就绪(缓冲区没满)

异常:网络情况中,select能处理的异常情况只有一种,socket接收到外带数据。

select系统调用:

pool系统调用:

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

1、同select,也是在指定时间内,轮询一定数量的文件描述符。以测试其中是否就绪者。(轮询:因为是数组所以需要一个一个的遍历)

2、select API:

int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval * timeout);

从左到右参数依次为被监听的文件描述符的总数、可读、可写、异常事件对应的文件描述符的集合。

fd_set结构体仅包含一个整型数组,该数组的每个元素的每一位都标记了一个文件描述符。没有将文件描述符和事件绑定,不能处理更多类型的事件,另一方面由于内核对fd_set的在线修改,应用程序下次调用select得对这3个参数进行重置。

如果在超时时间内没有任何就绪事件则selet返回0.失败返回-1并设置errno值。

2、pool API:

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

fds是一个pollfd结构类型的数组,他指定所有我们感兴趣的文件描述符的可读、可写、和异常事件等。(fds和下面的的fd意义不同fd是特定的)

 

poll系统返回值的意义和select相同。

 

fd成员指定文件描述符;events策划哪个院告诉poll监听fd上的哪些事件,它是一系列事件的按位或;revents则成员则有内核修改,已通知fd实际发生了哪些事件。将文件描述符和事件绑定,任何事件都被统一处理。并且每次内核修改的都是revents成员,events成员不变,下次调用poll时无需重置pollfd的事件集参数。

3、最多可处理1024个文件描述符,set结构体中有1024个位。这个位是由一个宏表示的。

3、处理的文件描述符比select多,最多有65536个

4、处理外带数据(可能要处理两种事件)

 

poll的事件类型更具体一点。

5、例如去图书馆领书,一个人去领,轮到是给谁打电话,不用每个人都去等,只用最后去领。

5、大概思想同select.

select:fd_set的整型数组共1024位    poll:  pollfd结构数组最大65536

读事件

1

0

0

1

1

0

0

......

写事件

1

0

1

0

0

0

0

......

异常

0

1

0

1

1

1

1

......

select、和poll调用过程

 

epoll系统调用:

实现:是linux特有的I/O复用函数。它在实现上和使用上与select和poll有着很大的差异。epoll使用一组函数来完成任务,而不是单个函数。epoll把用户关心的文件描述符上的事件放在一个内核事件表中。从而无需像select和poll那样每次调用都要重复传入文件描述符或者事件集。哪个描述符有事件就绪,内核通过回调函数将其添加到就绪队列。

所使用函数:

 

1、epoll需要一个额外的文件描述符,来唯一标识内核中的这个事件表。这个文件描述符使用如下函数创建。

int  epoll_create(int size)

size只是给内核一个提示,告诉它事件表需要多大。该函数返回的文件描述符将用作其他所有epoll系统调用的第一个参数,以指定要访问的内核事件表。

2、下面函数用来操作内核事件表:

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

(1)fd参数是要操作的文件描述符,op参数指定操作类型,有如下三种:

(2)event参数指定事件,它是epll_event结构指针类型,定义如下:

①event成员描述事件类型。epoll支持的事件类型和poll基本相同。表示epoll事件类型的宏就是在poll相对应得宏前面加上“E”。epoll有两个额外的事件类型——EPOLLET和EPOLLONESHOT。他们对于epoll高效运作非常关键。

②data用于存储用户数据。epoll_data_t的定义如下:

3、epoll系列系统调用的主要接口是epoll_wait函数。它在超时时间内等待一组文件描述符上的事件,原型如下:

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

      该函数成功返回就绪文件描述符的个数,失败时返回-1并设置errno.maxevents指定最多监听多少个事件。

      epoll_wait函数如果检测到事件,就将就绪的事件从内核事件表(epfd参数指定)复制到events指向的数组中。这个数组只用于输出epoll_wait检测到的就绪事件,而不像select和poll的数组参数那样即用于传入用户注册的事件,又输出内核检测到的事件。这就极大的提高了应用程序索引就绪 描述符的效率。

 

epoll_wait函数调用后就返回了所有的就绪文件描述符,而poll还需要遍历所有的已注册的文件描述符并找到其中的就就绪者。

2、epoll_ctl  添加 删除 修改

添加=》注册回调函数 epoll_poll_callback,当描述符上有数据就绪时,用设备驱动程序调用回调函数,将描述符和事件添加到就绪队列rdlist中。

3、当rdlist有数据时,将其拷贝到用户空间,就绪事件拷贝到用户空间,就绪事件个数.作为返回值,也就是拷到用户空间的数目。

 

ET模式与LT模式:select都只能工作于LT模式,而epoll可工作于LT模式和ET模式

LT

ET

多次触发直至数据处理完成

只触发一次,比较高效。

 

若一个文件描述符上的数据比较多,那么当若采用LT模式的话,其他的文件描述符就不会被处理,所以ET比LT高效

LT:input:hello (一次只接受一个)                 ET :input:hello(一次只接受一个)

客户端(反复提醒)h                                        h

e                                                                           input:ad

l                                                                            e

l

o

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值