基本套接字编程(5) -- epoll篇
1. epoll技术
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。 相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多。并且,在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE 1024
表示select最多同时监听1024个fd,当然,可以通过修改头文件再重编译内核来扩大这个数目,但这似乎并不治本。
2. epoll系统调用
epoll技术的接口实现非常简单,相关系统调用:- epoll_create() or epoll_create1
- epoll_ctl()
- epoll_wait()
2.1 句柄创建 -- epoll_create()
#include int epoll_create(int size);
int epoll_create1(int flags);
返回值:epoll句柄
首先:epoll_create()创建一个epoll的事例,通知内核需要监听size个fd。size指的并不是最大的后备存储设备,而是衡量内核内部结构大小的一个提示。当创建成功后,会占用一个fd,所以记得在使用完之后调用close(),否则fd可能会被耗尽。
Note:自从Linux2.6.8版本以后,size值其实是没什么用的,不过要大于0,因为内核可以动态的分配大小,所以不需要size这个提示了。 其次:epoll_create1()函数,其实它和epoll_create差不多,不同的是epoll_create1函数的参数是flag;
- 当flag是0时,表示和epoll_create函数完全一样,不需要size的提示了;
- 当flag = EPOLL_CLOEXEC,创建的epfd会设置FD_CLOEXEC;
- 当flag = EPOLL_NONBLOCK,创建的epfd会设置为非阻塞。
Note:关于FD_CLOEXEC,它是fd的一个标识说明,用来设置文件close-on-exec状态的。当close-on-exec状态为0时,调用exec时,fd不会被关闭;状态非零时则会被关闭,这样做可以防止fd泄露给执行exec后的进程。
2.2 事件注册 -- epoll_ctl()
#include int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
返回值:成功返回0 失败返回-1,errno设置为错误码 epoll的事件注册函数,它不同于select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。 - 第一个参数是epoll_create()的返回值;
- 第二个参数表示动作,用三个宏来表示:
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
- 第三个参数是需要监听的fd。
- 第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:
typedef union epoll_data { void *ptr;
int fd;
uint32_t u32;
uint64_t u64;} epoll_data_t;struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
