열렬히.뛰기

12. 멀티플랙싱 : epoll()

네트워크 > 소켓 프로그래밍 > 소켓 프로그래밍 > 12. 멀티플랙싱 : epoll()

select의 대체함수

select 기반의 멀티플랙싱 서버는 다음과 같은 특징이 있다.

  1. select 호출 시마다 매번 운영체제에 fd에 관한 정보를 전달.
  2. 반복문을 통한 파일 디스크립터 각각에 대한 접근
c
// 1번
cpy_reads = reads;

...

// 2번
for (int i = 0; i < fd_max + 1; i++)
	{
		if (FD_ISSET(i, &cpy_reads))
		{
			if (i == serv_sock) ...

무조건 대체함수?

  • 그러나 이러한 대체함수가 항상 만능은 아니다.
  • epoll, kqueue와 같은 함수는 운영체제에 따라서 사용에 제약이 있다.
  • 또한 서버의 접속자 수가 많지 않을 경우에도 불필요하다.

epoll

주로 리눅스 계열에서 쓰는 i/o 멀티플랙싱 전용 함수들

  1. 반복문에서 상태변화의 확인을 위한 부분이 필요없다.
  2. select 함수에 대응하는 epoll_wait 함수 호출시, 정보를 매번 전달할 필요가 없다.

epoll_create

c
#include <sys/epoll.h>

int epoll_create(int size);
  • size : fd 저장소의 크기.
  • 반환값 : fd 저장소를 가리키는 파일 디스크립터.
    • fd 저장소를 epoll 인스턴스라고 한다.

epoll_ctl

소켓 fd를 등록하는 함수.

c
#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • epfd : epoll 인스턴스의 파일 디스크립터
  • op : 관찰대상의 추가, 삭제 또는 변경여부 지정
    • 여기에 들어가는 상수들이 존재한다.
  • fd : 등록할 소켓 fd
  • event : fd를 저장할 곳.

epoll_wait

c
#include <sys/epoll.h>

int epoll_wait(int epfd, struct epoll_event *events, 
								int maxevents, int timeout);
  • epfd : epoll 인스턴스의 fd
  • events : 이벤트를 담는 배열
  • maxevents : events에 등록 가능한 최대 이벤트 갯수
  • timeout : 대기시간 (밀리세컨 = 0.001초 단위)

events에서 이벤트가 벌어진 fd를 찾아 그 수를 반환.

몇 개의 fd에서 이벤트가 벌어졌는지 확인할 수 있다.

epoll_event는 다음과 같이 생겼다.

c
struct epoll_event
{
	__uint32_t events; // 관찰하고자 하는 event
	epoll_data_t data; // 이벤트와 관련된 추가 데이터
}

typedef union epoll_data
{
	void *ptr;
	int fd;
	__uint32_t u32;
	__uint64_t u64;
} epoll_data_t;

따라서 모든 소켓 fd를 검사하지 않고, 이벤트가 발생한 일부만 검사하면 된다.

레벨 트리거와 엣지 트리거

트리거 : 일반적으로 특정 이벤트가 발생했을 때 특정 동작이나 처리가 시작되도록 하는 메커니즘.

레벨 트리거와 소켓

입력버퍼에 데이터가 있으면 계속해서 이벤트가 등록되는 것

엣지 트리거와 소켓

입력버퍼에 데이터가 있으면 1번만 이벤트가 등록되는 것