11:00起床
11:30-12;00
14:00学习
GitHub - chaixiang2002/cppserver (githubfast.com)
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 data variable */
} __EPOLL_PACKED;
epoll_event.data是一个union,可以是一个指针、一个fd、一个u32、一个u64
class Channel{
private:
Epoll *ep;
int fd;
uint32_t events;
uint32_t revents;
bool inEpoll;
};
events
表示希望监听这个文件描述符的哪些事件revents
表示在epoll
返回该Channel
时文件描述符正在发生的事件inEpoll
表示当前Channel
是否已经在epoll
红黑树中
如果我们希望监听该Channel
上发生的读事件,需要调用一个enableReading
函数:
void Channel::enableReading(){
events = EPOLLIN | EPOLLET;
ep->updateChannel(this);
}
可以看到该函数做了两件事,将要监听的事件events
设置为读事件并采用ET模式,然后在ep指针指向的Epoll红黑树中更新该Channel
,updateChannel
函数的实现如下:
void Epoll::updateChannel(Channel *channel){
int fd = channel->getFd(); //拿到Channel的文件描述符
struct epoll_event ev;
bzero(&ev, sizeof(ev));
ev.data.ptr = channel;
ev.events = channel->getEvents(); //拿到Channel希望监听的事件
if(!channel->getInEpoll()){
errif(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1, "epoll add error");//添加Channel中的fd到epoll
channel->setInEpoll();
} else{
errif(epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1, "epoll modify error");//已存在,则修改
}
}
事件驱动???传统的请求驱动模型?
事件的捕获、通信、处理和持久保留是解决方案的核心结构。libevent就是一个著名的C语言事件驱动库。