I / O 다 중 재 활용 epoll

지난 장 에서 우 리 는 select 에 대해 대체적으로 묘 사 를 했 고 전통 적 인 차단 식 서비스 에 비해 병행 도 를 높 였 다 는 것 을 알 게 되 었 으 나 문의 로 인해 효율 이 떨 어 졌 다.본 고 는 epoll 에 대해 설명 하고 자 한다. select 에 비해 병행 도가 높 고 현대 고 부하 서버 는 이런 모델 을 많이 사용한다.
    
    epoll 의 구체 적 인 용법 을 설명 하기 전에, 우 리 는 먼저 채택 을 살 펴 보 자.
epoll 모델 에 주로 사용 되 는 세 가지 함수 와 하나의 데이터 구조.
    
 epoll 의 세 가지 주요 함수:
(1)int epoll_create(int size);
기능.  :epoll 전용 파일 설명 자 를 만 듭 니 다.
매개 변수  :size: 이 epoll fd 에서 주목 하 는 최대 socket fd 수 입 니 다.
반환 값: 생 성 된 파일 설명자 입 니 다.
 
(2)int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
기능. :epoll 파일 설명자 의 이 벤트 를 제어 합 니 다. 이 벤트 를 등록 하고 이 벤트 를 수정 하 며 이 벤트 를 삭제 할 수 있 습 니 다.
매개 변수 :epfd  :epollcreate 에서 생 성 된 epoll 전용 파일 설명자;
            op     :EPOLL_CTL_ADD 등록, EPOLLCTL_MOD 수정, EPOLLCTL_DEL 삭제;
            fd     :연 결 된 파일 설명자;
            이벤트: epoll이벤트 포인터;
반환 값: 0: 성공; 
            -1: 실패;
 
(3)int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
기능. :I / O 사건 의 발생 을 문의 하 다.
매개 변수 :epfd         :epollcreate 에서 생 성 된 epoll 전용 파일 설명자;
            events      :처리 할 이벤트 의 배열 을 되 돌려 줍 니 다.
            max 이벤트: 매번 처리 할 수 있 는 이벤트 수;
           timeout     :I / O 이벤트 가 발생 하 기 를 기다 리 는 시간 초과 값; -1. 차단 에 해당 하고 0 은 비 차단 에 해당 한다.
반환 값: > = 0: 발생 이벤트 수 를 되 돌려 줍 니 다. 
                -1  :잘못
    epoll 의 주요 데이터 구조:
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: 파일 설명자 에 읽 을 수 있 는 긴급 한 데이터 가 있 습 니 다.
EPOLLERR: 파일 설명자 에 오류 가 발생 했 습 니 다.
EPOLLHUP: 파일 설명자 가 끊 겼 습 니 다.
EPOLLET: 파일 설명자 에 이벤트 가 발생 했 습 니 다.
epoll 의 사용 은 매우 간단 합 니 다. 다음 간단 한 epoll 로 동시 다발 서 비 스 를 제공 하 는 서버 프로그램 을 보십시오.
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/time.h>

#define MAXBUF 1024
#define MAX_EPOLL_SIZE 10000
#define SERVICE_PORT 8888


int main(int argc, char **argv)
{
        int server_fd, new_fd;
        struct sockaddr_in server_addr, client_addr;

        struct epoll_event ev;
        struct epoll_event events[MAX_EPOLL_SIZE];

        socklen_t len = sizeof(struct sockaddr_in);
        server_fd = socket(AF_INET, SOCK_STREAM, 0);

        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(SERVICE_PORT);
        server_addr.sin_addr.s_addr = INADDR_ANY;

        bind(server_fd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr));
        listen(server_fd, 1000);

        //create epoll fd, and register the server listening fd
        int epoll_fd = epoll_create(MAX_EPOLL_SIZE);
        ev.events = EPOLLIN | EPOLLET;
        ev.data.fd = server_fd;
        epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);

        int active_fd_count = 1;
        while (1)
        {
                //wait for some events to happen
                int event_active_fd_count = epoll_wait(epoll_fd, events, active_fd_count, -1);

                // process all events
                for (int i = 0; i < event_active_fd_count; ++i)
                {
                        if (events[i].data.fd == server_fd)
                        {
                                new_fd = accept(server_fd, (struct sockaddr *) &client_addr,&len);

                                //register new fd to epoll
                                ev.events = EPOLLIN | EPOLLET;
                                ev.data.fd = new_fd;
                                epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &ev);
                                active_fd_count++;
                        }
                        else
                        {
								handle message on events[i].data.fd
                                if (client close the connection)
                                {
                                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd,&ev);
                                        active_fd_count--;
                                }
                        }
                }
        }
        close(server_fd);
        return 0;
}

    epoll 의 일반적인 사용 방법 을 말 하고 여기 서 주의해 야 할 것 은 epoll 에 두 가지 작업 방식 이 있 습 니 다.
       (1)ET:Edge  Triggered, 가장자리 트리거.상태 가 바 뀌 었 을 때 만 알려 주 고 모든 요청 을 세밀 하 게 처리 해 야 합 니 다. 그렇지 않 으 면 분실 사건 이 발생 하기 쉽 습 니 다.차단 되 지 않 은 socket 만 지원 합 니 다.
       (2) LT: Level Triggered, 수평 트리거 (기본 작업 방식).처리 되 지 않 은 사건 이 있 으 면 계속 알려 주기 때문에 사건 분실 은 걱정 하지 않 아 도 된다.효율 은 ET 트리거 보다 낮 을 것 이다. 특히 큰 병발, 큰 유량 의 경우.차단 과 비 차단 을 지원 하 는 socket 입 니 다.
         마지막 으로 강의 하 다
왜 epoll 이 select 보다 효율 적 이 고 주로 세 가지 측면 에서 논술 합 니까?
        (1) elect 가 설명자 상태 에 대한 변 화 는 폴 링 을 통 해 찾 습 니 다.한편, epoll 은 설명자 상태 가 바 뀌 었 을 때 자발적으로 커 널 을 알 리 는 것 이 이른바 Reactor 이벤트 처리 체제 입 니 다.할리우드 원칙 으로 묘사 할 수 있다. 우리 에 게 전화 하지 마라. 우 리 는 너 에 게 전 화 를 할 것 이다.이에 비해 select 의 메커니즘 은 면접 이 끝 난 후 끊임없이 면접 관 에 게 전 화 를 걸 어 면접 결 과 를 묻 는 것 과 같다.효율 이 어느 것 이 높 고 어느 것 이 낮은 지 알 수 있다. 반점
        
       (2) select 의 파일 설명 자 는 링크 를 사용 하여 조직 한 것 이다.epoll 은 붉 은 검 은 나무 라 는 효율 적 인 데이터 구 조 를 사용 하여 조직 한 것 이다.
        
       (3) select 가 커 널 에서 사용자 공간 으로 파일 설명자 에 보 낸 정 보 는 메모리 복사 방식 으로 이 루어 집 니 다.epoll 은 메모리 공유 방식 을 사용 합 니 다.

좋은 웹페이지 즐겨찾기