概述
目录
- Epoll - IO多路复用
- 怎么理解
- 创建Epoll
- 向EPOLL对象中添加、修改或者删除感兴趣的事件
- 收集在epoll监控的事件中已经发生的事件
- 完整代码
Epoll - IO多路复用
怎么理解
类比快递员寄快递,传统方式是快递员挨家挨户上楼敲门现,在改为用快递柜子的方式,比如丰巢类似,现在这里有两个集合。
1.住户所有人是一个集合。
2.丰巢是一个子集,比如今天要寄快递的住户。
epoll就是管理这两个集合。
epoll_create相当于一栋楼,聘请了一个快递员,创建一栋楼
epoll_ctl往楼里搬住户,它具备三个功能:
1.是往这栋楼搬一个住户进来。
2.一个用户搬出来。
3.比如一个用户从7楼搬到8楼
分别对应下面三种,增删改。
epoll_ctl(ADD,DEL,MOD)
epoll_wiat是快递员多久来丰巢取一次快递
创建Epoll
int epoll_create(int size);
参数:
size:只要大于0即可,如果传一个<=0是不可用的
实际上,这里你传1或者10000区别是不大的,那为什么还需要这个参数呢?
早先版本的epoll他的队列大小是用size来定义的,也就是"“快递柜”"的大小,而后来不使用此参数的原因是其改为了链表存储(动态),保留此参数是为了保证代码的兼容.
创建完后还要准备一个东西 ----- epoll_event
这就好比快递员从快递柜拿快递走,不可能整个快递柜都搬走,这里就类比成一个袋子,或者一个小推车,用来装快递柜里的快递,这个我们就要定义大小了
struct epoll_event event[设置大小POLL_SIZE] = {0};
//多大合适的问题?
//假设快递柜有50个格子,你的推车只能装10个,那么跑5趟即可.
//这里只是跑的次数多少而已,对数量没有要求,设置的大,跑的次数少,设置的小,跑的次数多
//而且这个小车大小是可变的,初始不要设置太小
结构原型
struct epoll_event{
__uint32_t events;
epoll_data_t data;
}
typedef union epoll_data{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
}epoll_data_t
向EPOLL对象中添加、修改或者删除感兴趣的事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
op取值:EPOLL_CTL_ADD 添加新的事件到epoll中
EPOLL_CTL_MOD 修改EPOLL中的事件
EPOLL_CTL_DEL 删除epoll中的事件
events取值:
EPOLLIN 表示有数据可以读出(接受连接、关闭连接)
EPOLLOUT 表示连接可以写入数据发送(向服务器发起连接,连接成功事件)
EPOLLERR 表示对应的连接发生错误
EPOLLHUP 表示对应的连接被挂起
示例片段:
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = linstenfd;
epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
收集在epoll监控的事件中已经发生的事件
快递员去快递柜取出快递
int epoll_wait(int epfd,
struct epoll_event * events,
int maxevents,
int timeout);
epfd: epoll的描述符。
events:分配好的 epoll_event结构体数组,epoll将会把发生的事件复制到 events数组中
(events不可以是空指针,内核只负责把数据复制到这个 events数组中,不会去帮助我们在用户态中分配内存。内核这种做法效率很高)。
maxevents: 本次可以返回的最大事件数目,通常 maxevents参数与预分配的events数组的大小是相等的。
timeout: 表示在没有检测到事件发生时最多等待的时间(单位为毫秒),
如果timeout为0,立刻返回,不会等待。-1表示无限期阻塞
示例片段:
while(1)
{
int nready = epoll_wait(epfd, events, POLL_SIZE, 5);
//POLL_SIZE小车能装多少快递, 5毫秒去一趟
//nready返回事件个数
if(nready == -1)continue;
}
完整代码
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <pthread.h>
#define MAXLNE 4096
#define POLL_SIZE 1024
//8m * 4G = 128 , 512
//C10k
void *client_routine(void *arg) { //
int connfd = *(int *)arg;
char buff[MAXLNE];
while (1) {
int n = recv(connfd, buff, MAXLNE, 0);
if (n > 0) {
buff[n] = '