Skip to content

Study : CPP : epoll

마석우 edited this page Apr 4, 2022 · 1 revision
항목 내용
일자 2022.04.04
작성자 sma
제목 webserv 허용함수 - epoll
한줄요약 멀티 플렉싱 관련 함수

epoll

epoll 함수는 리눅스에서 select 의 단점을 보완하기 위해 만든 함수이다.

파일 디스크립터를 사용자가 아닌 커널이 관리하며, 그만큼 cpu는 계속해서 파일 디스크립터를 감시할 필요가 없다.

select 함수는 파일 디스크립터를 전부 FT_ISSET 루프를 돌려 이벤트가 발생한 fd 를 확인해야한다.

epoll 함수는 이벤트가 발생한 fd 만 구조체 배열을 통해 넘겨준다.

검사할 fd 수가 무제한이다.

epoll_create()

#include <sys/epoll.h>

int epoll_create(int size)

epoll_createepoll 인스턴스를 생성한다.

리눅스 2.6.8 이후부터 size 인자는 사용되지 않지만 0보다는 큰 값으로 설정해 주어야 한다. 커널은 필요한 데이터 구조의 크기를 동적으로 조정하기 때문에 0보다 큰 값만 입력하면 된다.

리턴 값은 epoll 인스턴스와 연관된 파일 디스크립터를 반환

실패 시 -1 반환

epoll_ctl()

#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

epoll_ctlepollfd 들을 등록/수정/삭제를 하는 함수

  • epfd : epoll fd
  • op : 관심가질 fd 를 등록할지, 등록되어 있는 fd 의 설정을 변경할지, 등록되어 있는 fd 를 관심 목록에서 제거할지에 대한 옵션값
EPOLL_CTL_ADD fd를 epfd의 관심 목록에 추가, 이미 목록에 존재한다면 EEXIST에러를 발생 시킨다. event 집합은 *event에 저장된다.
EPOLL_CTL_MOD *event에 지정된 정보를 이용해 fd 설정 변경, 관심 목록에 없는 fd 라면 ENOENT 에러를 발생시킨다.
EPOLL_CTL_DEL epfd에서 fd를 제공한다. epfd 관심 목록에 없는 fd를ㄹ 제거하려면 ENOENT 에러를 발생한다. fd를 닫으면 epoll 관심 목록에서 자동 제거된다.
  • fd : epfd 에 등록할 관심있는 파일 디스크립터 값
  • event : fd 에서 감시할 이벤트, 여러가지 이벤트들을 OR 연산으로 묶을 수 있다.
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 */
}
EPOLLIN 수신할 데이터가 있다.
EPOLLOUT 송신 가능하다.
EPOLLPRI 중요한 데이터(OOB) 발생
EPOLLRDHUD 연결 종료 또는 Half-close 발생
EPOLLERR 에러 발생
EPOLLET 엣지 트리거 방식으로 설정(기본은 레벨 트리거 방식)
EPOLLONESHOT 한번만 이벤트 받음

epoll_wait()

#include <sys/epoll.h>

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)

epoll_wait 은 관심있는 fd 들에 무슨일이 일어났는지 조사한다. 이벤트가 발생된 fd 들은 events 변수(이전에 선언한 변수가 아니라 새롭게 선언한 비어있는 events 변수) 에 담긴다. select 는 모든 fd 배열을 순회하면서 확인해야하지만 epoll 은 이렇게 이벤트가 발생한 fdevents 배열에 담아주기 때문에 리턴된 정수 값만큼만 events 배열을 확인하면 된다.

  • events : 이벤트가 발생된 fd 들을 모아놓은 구조체 배열(비어있는 epoll_event 변수를 넘겨준다)
  • maxevents : 최대 이벤트 처리 개수
  • timeout : select 와 동일 . -1로 지정하면 무한 blocking, 0이면 사건이 있건 없건 조사만 하고 즉시 리턴

Edge Trigger 과 Level Trigger

  • epoll에서는 Edge Triggerlevel Trigger 둘 중 하나를 선택해야 한다. 기본 설정은 level trigger

level-trigger 는 특정 준위가 유지되는 동안 감지

edge-trigger 는 특정 준위가 변화하는 시점에서만 감지

  • edge-trigger 일 경우 이벤트가 발생해서 1이 되었을 때만 발생한다. 만약 이벤트가 발생하고 데이터를 읽었는데, 버퍼의 데이터를 모두 읽지 못하고 다음 wait 함수를 호출 할 경우 남아 있는 데이터를 감지하지 못하고 계속 블록되는 문제가 발생한다.
  • edge-trigger 를 사용하려면 non-blocking 소켓에 사용해야 한다.
  • readwriteerrnoEGAIN 을 반환 할 때만 wait한다.