Tuesday, March 25, 2008

epoll()

epoll()은 multiplexed I/O 를 구현한 함수 중의 하나로 모니터할 fd의 수가 많아질 때 이전에 제공되던 select, poll 보다 성능이 좋은 함수이다. epoll()은 이전 함수들과는 달리 create, control, monitor의 세 단계로 함수를 나누어 제공한다. 먼저 이벤트 구조체에 대해 알아놓을 필요가 있는데,

# include <sys/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 */
} __attribute__ ((__packed__));

위 처럼 되어 있어 events에 EPOLLIN, EPOLLOUT 등 여러개의 모니터할 이벤트를 걸어놓을 수 있다. Union 으로 되어 있는 epoll_data에는 임의의 데이터를 넣을 수 있는데, 주로 관련 fd를 넣어 발생한 이벤트가 어떤 fd로 부터 였는지 확인할 때 사용한다. 이렇게 구조체를 사용하여 epoll은 아래의 세 함수를 통해 사용할 수 있다.

# include <sys/epoll.h>
// size는 fd 갯수
int epoll_create(int size);

// op = EPOLL_CTL_ADD, EPOLL_CTL_DEL 로 fd 추가,삭제
int epoll_ctl (int epfd,
int op,
int fd,
int struct epoll_event *event);

int epoll_wait (int epfd,
struct epoll_event *event,
int maxevents,
int timeout);
// epfd는 나중에 close()되어야 한다.

그래서 epoll 예제를 사용하는 예제를 하나 보면 아래와 같다.

# include <sys/epoll.h>

// 1. epoll create
int epfd;
// 대략 ~100개의 fd를 관찰할 계획
epfd = epoll_create(100);
if (epfd<0) perror("epoll_create");

// 2. add fd with events
struct epoll_event event;
int ret;
event.data.fd = fd; //모니터할 fd
event.events = EPOLLIN | EPOLLOUT;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
if (ret<0) perror("epoll_ctl");

// 3. monitoring
// 발견된 event들이 담길 배열의 포인터
struct epoll_event *events;
#define MAX_EVENTS 64
// 위에서 사용한 epfd를 쓰는 것인지 모르겠음
int nr_events, i, epfd2;
events = malloc(sizeof(struct epoll_event) * MAX_EVENTS);
if (!events) perror ("malloc");
// 무한 타임아웃
nr_events = epoll_wait(epfd2, events, MAX_EVENTS, -1);
if (nr_events<0) perror("epoll_wait");
for (i=0; i<nr_events; i++)
{
printf("event=%ld on fd=%d\n",
events[i].events,
events[i].data.fd);
}

No comments:

Post a Comment