1.epoll功能描述
1.1 将检测文件描述符的变化委托给内核去处理, 然后内核将发生变化的文件描述符对应的事件返回给应用程序。
2.eopll相关函数分析
2.1 int epoll_create(int size)
2.1.1 函数说明: 创建一个树根
2.1.2 参数说明:
size: 最大节点数, 此参数在linux 2.6.8已被忽略, 但必须传递一个大于0的数。
2.1.3 返回值:
成功: 返回一个大于0的文件描述符, 代表整个树的树根。
失败: 返回-1, 并设置errno值。
2.2 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
2.2.1 函数说明: 将要监听的节点在epoll树上添加, 删除和修改。
2.2.2 参数说明:
epfd: epoll树根
op:
EPOLL_CTL_ADD: 添加事件节点到树上
EPOLL_CTL_DEL: 从树上删除事件节点
EPOLL_CTL_MOD: 修改树上对应的事件节点
fd: 事件节点对应的文件描述符
event: 要操作的事件节点
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 监听的事件类型 */
epoll_data_t data; /* 存放用户的相关变量信息 */
};
events常用的有:
EPOLLIN: 读事件
EPOLLOUT: 写事件
EPOLLERR: 错误事件
EPOLLET: 边缘触发模式
fd: 要监控的事件对应的文件描述符
2.2.3 返回值:
成功: 返回0
失败: 返回-1, 并设置errno值
2.3 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
2.3.1 函数说明:等待内核返回事件发生
2.3.2 参数说明:
epfd: epoll树根
events: 传出参数, 其实是一个事件结构体数组
maxevents: 数组大小
timeout: 单位:毫秒ms
-1: 表示永久阻塞
0: 立即返回
>0: 表示超时等待事件
2.3.3 返回值:
成功: 返回发生事件的个数。
失败: 若timeout=0, 没有事件发生则返回; 返回-1, 设置errno值。
3. epoll的两种工作模式
3.1 epoll的两种模式ET和LT模式
3.1.1 水平触发(LT): 高电平代表1
只要缓冲区中有数据, 就一直通知。
3.1.2 边缘触发(ET): 电平有变化就代表1
缓冲区中有数据只会通知一次, 之后再有数据才会通知(若是读数据的时候没有读完, 则剩余的数据不会再通知, 直到有新的数据到来)。
3.2 epoll默认工作模式
epoll默认工作模式是LT模式。
4.epoll优化
4.1 ET模式由于只通知一次, 所以在读的时候要循环读, 直到读完, 但是当读完之后read就会阻塞, 所以应该将该文件描述符设置为非阻塞模式。
4.2 边缘非阻塞模式: 提高效率。
5.epoll使用源码
5.1 源码功能介绍:epoll服务器等待客户端的连接到来,接收客户端发过来的信息并回复。
5.2 源码展示
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <sys/epoll.h>
#include <fcntl.h>
int main()
{
int n;
int i;
int nready;
int lfd;
int cfd;
int sockfd