-
Notifications
You must be signed in to change notification settings - Fork 0
Study : CPP : epoll
마석우 edited this page Apr 4, 2022
·
1 revision
항목 | 내용 |
---|---|
일자 | 2022.04.04 |
작성자 | sma |
제목 | webserv 허용함수 - epoll
|
한줄요약 | 멀티 플렉싱 관련 함수 |
epoll
함수는 리눅스에서 select
의 단점을 보완하기 위해 만든 함수이다.
파일 디스크립터를 사용자가 아닌 커널이 관리하며, 그만큼 cpu는 계속해서 파일 디스크립터를 감시할 필요가 없다.
select
함수는 파일 디스크립터를 전부 FT_ISSET
루프를 돌려 이벤트가 발생한 fd
를 확인해야한다.
epoll
함수는 이벤트가 발생한 fd
만 구조체 배열을 통해 넘겨준다.
검사할 fd
수가 무제한이다.
#include <sys/epoll.h>
int epoll_create(int size)
epoll_create
는 epoll
인스턴스를 생성한다.
리눅스 2.6.8 이후부터 size
인자는 사용되지 않지만 0보다는 큰 값으로 설정해 주어야 한다. 커널은 필요한 데이터 구조의 크기를 동적으로 조정하기 때문에 0보다 큰 값만 입력하면 된다.
리턴 값은 epoll
인스턴스와 연관된 파일 디스크립터를 반환
실패 시 -1 반환
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
epoll_ctl
은 epoll
에 fd
들을 등록/수정/삭제를 하는 함수
-
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 | 한번만 이벤트 받음 |
#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
은 이렇게 이벤트가 발생한 fd
를 events
배열에 담아주기 때문에 리턴된 정수 값만큼만 events
배열을 확인하면 된다.
-
events
: 이벤트가 발생된fd
들을 모아놓은 구조체 배열(비어있는epoll_event
변수를 넘겨준다) -
maxevents
: 최대 이벤트 처리 개수 -
timeout
:select
와 동일 . -1로 지정하면 무한 blocking, 0이면 사건이 있건 없건 조사만 하고 즉시 리턴
- epoll에서는 Edge Trigger과 level Trigger 둘 중 하나를 선택해야 한다. 기본 설정은 level trigger
level-trigger 는 특정 준위가 유지되는 동안 감지
edge-trigger 는 특정 준위가 변화하는 시점에서만 감지
- edge-trigger 일 경우 이벤트가 발생해서 1이 되었을 때만 발생한다. 만약 이벤트가 발생하고 데이터를 읽었는데, 버퍼의 데이터를 모두 읽지 못하고 다음 wait 함수를 호출 할 경우 남아 있는 데이터를 감지하지 못하고 계속 블록되는 문제가 발생한다.
- edge-trigger 를 사용하려면 non-blocking 소켓에 사용해야 한다.
-
read
나write
가errno
로 EGAIN 을 반환 할 때만 wait한다.