1000sj
SJ CODE
1000sj
전체 방문자
오늘
어제
  • 분류 전체보기
    • 네트워크 보안
      • 네트워크
      • 보안
      • CTF
      • CVE
    • 알고리즘
    • System Programming
      • Operating System
      • Device Driver
      • Emulator
    • Application Programming
      • Script
      • Android
    • 클라우드 컴퓨팅
      • Cloud Native
      • Public Cloud
      • Infrastructure
      • Database
    • 트러블슈팅
    • ETC
      • 문화 생활
      • 커뮤니티

인기 글

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
1000sj

SJ CODE

네트워크 보안/네트워크

[C/C++] epoll

2024. 7. 30. 10:00

Epoll

epoll은 select의 단점을 보완하여 사용할 수 있도록 만든 I/O 통지 모델이다. 파일 디스크립터를 사용자가 아닌 커널이 관리하며 그만큼 cpu 는 계속해서 파일 디스크립터의 상태 변화를 감시할 필요가 있다. 즉 select 처럼 어느 파일 디스크립터에 이벤트가 발생하였는지 찾기 위해 전체 파일디스크립터에 대해서 순차 검색을 위한 FD_ISSET 루프를 돌려야 하지만 Epoll의 경우 이벤트가 발생한 파일 디스크립터들만 구조체 배열을 통해 넘겨주므로 메모리 카피에 대한 비용이 줄어든다.

 

Epoll의 주요기능

- non block I/O 지: epoll은 non block 모드로 파일 디스크립터를 처리할 수 있다.

- 높은 성능: 파일 디스크립터 집합을 다룰 때 매우 효율적이다.

- Edge Trigger(ET), Level Trigger(LT): epoll은 두가지 모드로 동작할 수 있다.

 

Epoll 주요함수

- epoll_create1: epoll 인스턴스를 생성한다.

- epoll_ctl: 파일 디스크립터를 epoll 인스턴스에 추가, 수정, 삭제한다.

- epoll_wait: 이벤트가 발생할 때까지 대기한다. 

 

struct epoll_event: epoll_event 구조체는 감시할 파일 디스크립터의 이벤트 유형과 사용자 데이터를 포함한다.

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 */
};

 

  • events: 감지할 이벤트의 비트 마스크. 여러 이벤트를 OR 연산자로 결합할 수 있습니다.
    • EPOLLIN: 수신할 데이터가 있습니다.
    • EPOLLOUT: 송신할 준비가 되었습니다.
    • EPOLLPRI: 중요 데이터(OOB)가 수신되었습니다.
    • EPOLLRDHUP: 연결 종료 또는 반닫기(Half-close)가 발생했습니다.
    • EPOLLERR: 에러가 발생했습니다.
    • EPOLLET: 엣지 트리거 방식으로 설정합니다. 기본은 레벨 트리거 방식입니다.
    • EPOLLONESHOT: 한 번만 이벤트를 받습니다. 이벤트가 발생한 후에는 다시 설정해야 합니다.
  • data: 사용자 데이터. 이벤트가 발생한 파일 디스크립터 또는 사용자 정의 포인터를 포함할 수 있습니다.

 

 

Epoll 함수 Usage

#include <sys/epoll.h>

int epoll_create1(int flags);
  • flags: epoll 인스턴스를 생성할 때 사용할 추가 옵션을 지정합니다. 예를 들어, EPOLL_CLOEXEC 플래그를 사용할 수 있습니다. 만약 특별한 플래그를 지정하지 않으려면 0을 전달하면 됩니다.
    • EPOLL_CLOEXEC: 이 플래그를 설정하면 exec 계열의 함수 호출 시 생성된 epoll 파일 디스크립터가 자동으로 닫힙니다. 이는 자식 프로세스가 불필요하게 파일 디스크립터를 상속받는 것을 방지하기 위해 사용됩니다.
  • 성공 시: 새로 생성된 epoll 인스턴스의 파일 디스크립터를 반환합니다.
  • 실패 시: -1을 반환하며, errno를 통해 에러를 설명할 수 있습니다.

 

 

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

 

  • epfd: epoll 인스턴스의 파일 디스크립터.
  • op: 수행할 작업. EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL 중 하나.
    • EPOLL_CTL_ADD: fd를 epfd의 관심 목록에 추가합니다. 이미 목록에 존재한다면 EEXIST 에러를 발생시킵니다.
    • EPOLL_CTL_MOD: event에 지정된 정보를 이용해 fd의 설정을 변경합니다. 관심 목록에 없는 fd라면 ENOENT 에러를 발생시킵니다.
    • EPOLL_CTL_DEL: epfd에서 fd를 제거합니다. 관심 목록에 없는 fd를 제거하려면 ENOENT 에러를 발생시킵니다. fd를 닫으면 epoll 관심 목록에서 자동으로 제거됩니다.
  • fd: epoll 인스턴스에 추가, 수정 또는 삭제할 파일 디스크립터.
  • event: epoll 이벤트를 설명하는 구조체. 파일 디스크립터의 관심 이벤트와 사용자 데이터를 포함.

 

 

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

 

  • epfd: epoll 인스턴스의 파일 디스크립터입니다.
  • events: 이벤트가 발생한 파일 디스크립터의 목록을 저장할 배열입니다.
    • epoll_event 구조체 배열입니다. 이벤트가 발생한 파일 디스크립터들이 여기에 저장됩니다.
    • 각 배열 요소는 struct epoll_event 타입입니다.
    • 예를 들어, struct epoll_event events[MAX_EVENTS];와 같이 정의할 수 있습니다.
  • maxevents: 처리할 수 있는 최대 이벤트 수를 지정합니다.
    • 한
    • 번에 처리할 최대 이벤트 수를 지정합니다.
    • 이 값을 통해 이벤트 배열의 크기를 제한할 수 있습니다.
    • 예를 들어, maxevents를 10으로 설정하면 한 번에 최대 10개의 이벤트만 처리합니다.
  • timeout: 대기 시간(밀리초)입니다.

 

 

 

#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define MAX_EVENTS 10

int make_non_blocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1) {
        perror("fcntl");
        return -1;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
        perror("fcntl");
        return -1;
    }
    return 0;
}

파일 디스크립터를 non blocking 모드로 설정한다. 

int main() {
    int epoll_fd, nfds;
    struct epoll_event event, events[MAX_EVENTS];

    // epoll 인스턴스 생성
    epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("epoll_create1");
        exit(EXIT_FAILURE);
    }

    // 표준 입력을 비차단 모드로 설정
    if (make_non_blocking(STDIN_FILENO) == -1) {
        close(epoll_fd);
        exit(EXIT_FAILURE);
    }

    // 이벤트 설정
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = STDIN_FILENO;

epoll_create1에서 epoll 인스턴스를 생성한다.

 

    // 파일 디스크립터를 epoll 인스턴스에 추가
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event) == -1) {
        perror("epoll_ctl");
        close(epoll_fd);
        exit(EXIT_FAILURE);
    }

epoll_ctl에서 표준입력(stdin)을 epoll 인스턴스에 추가하고 EPOLLIN 및 EPOLLET 이벤트를 설정한다.

 

    // 이벤트 감시 루프
    while (1) {
        nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        if (nfds == -1) {
            if (errno == EINTR) {
                continue; // 인터럽트된 경우 다시 대기
            }
            perror("epoll_wait");
            close(epoll_fd);
            exit(EXIT_FAILURE);
        }

        // 감지된 이벤트 처리
        for (int n = 0; n < nfds; ++n) {
            if (events[n].events & EPOLLIN) {
                printf("Read event on file descriptor %d\n", events[n].data.fd);
                char buf[512];
                ssize_t count;
                while ((count = read(events[n].data.fd, buf, sizeof(buf))) > 0) {
                    printf("Read %zd bytes: %.*s", count, (int)count, buf);
                }
                if (count == -1 && errno != EAGAIN) {
                    perror("read");
                    close(epoll_fd);
                    exit(EXIT_FAILURE);
                }
            }
        }
    }

    close(epoll_fd);
    return 0;
}

epoll_wait에서 이벤트가 발생할 때까지 대기한다.

 

 

'네트워크 보안 > 네트워크' 카테고리의 다른 글

strongswan #1 IKEv2 소프트웨어 아키텍쳐, 메세지 포맷, config 설정 및 실행 방법  (0) 2024.11.03
TCP/IP Stack 개발 #1 Ethernet & ARP  (0) 2024.08.04
Scalable Network Programming  (3) 2024.03.18
[Python/ MQTT] MQTT – Pub/Sub 모델 구현  (2) 2022.08.26
[Django] Jump to Django (02/admin)  (0) 2022.06.30
    '네트워크 보안/네트워크' 카테고리의 다른 글
    • strongswan #1 IKEv2 소프트웨어 아키텍쳐, 메세지 포맷, config 설정 및 실행 방법
    • TCP/IP Stack 개발 #1 Ethernet & ARP
    • Scalable Network Programming
    • [Python/ MQTT] MQTT – Pub/Sub 모델 구현
    1000sj
    1000sj

    티스토리툴바