linux의 epoll의 사용방법과 동작원리 이해
epoll은 epoll_create --> epoll_wait을 통해 생성된 epoll로부터 fd의 이벤트를 감지하여 일어난 이벤트에 한해서 추가 동작을 실행할 수 있다
만약 이벤트가 발생했을 시,
선언해준 epoll_wait(fd_epoll, events[struct epoll_event], maxEvent, timeout)에서 두번째인 events 배열에 이벤트가 앞쪽부터 생성된다.
epoll.h
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.ptr을 통해 일어난 이벤트의 포인터로 접근할 수 있으며 또한 fd로도 접근할 수 있다.
그리고 epoll_event.events는 어떠한 이벤트의 조건인지 알려주는데 아래와 같이 분류된다.
/* Event types that can be polled for. These bits may be set in `events'
to indicate the interesting event types; they will appear in `revents'
to indicate the status of the file descriptor. */
#define POLLIN 0x001 /* There is data to read. */
#define POLLPRI 0x002 /* There is urgent data to read. */
#define POLLOUT 0x004 /* Writing now will not block. */
/* Event types always implicitly polled for. These bits need not be set in
`events', but they will appear in `revents' to indicate the status of
the file descriptor. */
#define POLLERR 0x008 /* Error condition. */
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
크게 분류하자만 none-event, read-event(POLLIN, POLLPRI), write-event(POLLOUT) 분류할 수 있겠다.
if( (revents_ & POLLHUP) && !(revents_ & POLLIN))
{
LOG_TRACE<<"handle close";
if(closeCallback_)
closeCallback_();
}
if(revents_ & (POLLNVAL | POLLERR))
{
LOG_TRACE<<"handle error";
if(errorCallback_)
errorCallback_();
}
if(revents_ & (POLLIN | POLLPRI | POLLRDHUP))
{
LOG_TRACE<<"handle read";
if(readCallback_)
readCallback_();
}
if(revents_ & POLLOUT)
{
LOG_TRACE<<"handle write";
if(writeCallback_)
writeCallback_();
}
update(EPOLL_CTL_ADD, channel);
update(EPOLL_CTL_DEL, channel);
update(EPOLL_CTL_MOD, channel);
Events
EPOLLIN - 수신할 데이터가 있다
EPOLLOUT - 송신 가능하다
EPOLLPRI - 중요한 데이터(OOB) 발생
EPOLLRDHUD - 연결 종료 또는 Half-close 발생
EPOLLERR - 에러 발생
EPOLLET - 엣지 트리거 방식으로 설정(기본은 레벨 트리거 방식)
EPOLLONESHOT - 한번만 이벤트 받음
epoll_wait로 이벤트가 일어난 갯수를 리턴
0보다 일어난 갯수가 많으면
for문으로 epoll_event를 하나씩 하나씩 onEvent 해줌