设为首页 加入收藏

TOP

Epoll模型详解(一)
2011-12-14 13:02:01 】 浏览:19652
Tags:Epoll 模型 详解
           linux 的网络编程(www.cppentry.com)中,很长的时间都在使用 select 来做事件触发。在 linux 新的内核中,有了一种替换它的机制,就是 epoll 

    相比于 select  epoll 最大的好处在于它不会随着监听 fd 数目的增长而降低效率。因为在内核中的 select 实现中,它是采用轮询来处理的,轮询的 fd 数目越多,自然耗时越多。并且,在 linux/posix_types.h 头文件有这样的声明:

#define __FD_SETSIZE    1024

表示 select 最多同时监听 1024  fd ,当然,可以通过修改头文件再重编译内核来扩大这个数目,但这似乎并不治本。

 

epoll 的接口非常简单,一共就三个函数:

1. int epoll_create(int size);

创建一个 epoll 的句柄, size 用来告诉内核这个监听的数目一共有多大。这个参数不同于 select() 中的第一个参数,给出最大监听的 fd+1 的值。需要注意的是,当创建好 epoll 句柄后,它就是会占用一个 fd 值,在 linux 下如果查看 /proc/ 进程 id/fd/ ,是能够看到这个 fd 的,所以在使用完 epoll 后,必须调用 close() 关闭,否则可能导致 fd 被耗尽。

 

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

epoll 的事件注册函数,它不同与 select() 是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

第一个 参数是 epoll_create() 的返回值,

第二个 参数表示动作,用三个宏来表示:

EPOLL_CTL_ADD :注册新的 fd  epfd 中;

EPOLL_CTL_MOD :修改已经注册的 fd 的监听事件;

EPOLL_CTL_DEL :从 epfd 中删除一个 fd 

第三个 参数是需要监听的 fd 

第四个 参数是告诉内核需要监听什么事, struct epoll_event 结构如下:

struct epoll_event {

  __uint32_t events;  /* Epoll events */

  epoll_data_t data;  /* User data variable */

};

 

events 可以是以下几个宏的集合:

EPOLLIN       表示对应的文件描述符可以读(包括对端 SOCKET 正常关闭);

EPOLLOUT      表示对应的文件描述符可以写;

EPOLLPRI        表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);

EPOLLERR       表示对应的文件描述符发生错误;

EPOLLHUP       表示对应的文件描述符被挂断;

EPOLLET         EPOLL 设为边缘触发 (Edge Triggered) 模式,这是相对于水平触发 (Level Triggered) 来说的。

EPOLLONESHOT  只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个 socket 的话,需要再次把这个 socket 加入到 EPOLL 队列里

 

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

等待事件的产生,类似于 select() 调用。参数 events 用来从内核得到事件的集合, maxevents 告之内核这个events 有多大,这个 maxevents 的值不能大于创建 epoll_create() 时的 size ,参数 timeout 是超时时间(毫秒, 0 会立即返回, -1 将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回 0 表示已超时。

 

 

 man 手册中,得到 ET  LT 的具体描述如下

 

EPOLL 事件有两种模型:

Edge Triggered (ET)  边缘触发 只有数据到来,才触发,不管缓存区中是否还有数据。

Level Triggered (LT)  水平触发 只要有数据都会触发。

 

假如有这样一个例子:

1. 我们已经把一个用来从管道中读取数据的文件句柄 (RFD) 添加到 epoll 描述符

2. 这个时候从管道的另一端被写入了 2KB 的数据

3. 调用 epoll_wait(2) ,并且它会返回 RFD ,说明它已经准备好读取操作

4. 然后我们读取了 1KB 的数据

5. 

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/13/13
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇libevent C 事件通知接口函数库 下一篇linux的epoll模型详解

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目