링크 ux 의 폴 링 메커니즘 select / poll / epol
8631 단어 링크 ux 응용 층
http://www.cnblogs.com/xuxm2007/archive/2011/08/15/2139809.html
http://xingyunbaijunwei.blog.163.com/blog/static/76538067201241685556302/
비교 하 다.
select
select 는 본질 적 으로 fd 표지 위 치 를 설정 하거나 검사 하 는 데이터 구 조 를 통 해 다음 처 리 를 합 니 다.이러한 단점 은 1 개의 프로 세 스 가 감시 할 수 있 는 fd 수량 이 제한 되 어 있 습 니 다. 2. 대량의 fd 를 저장 하 는 데이터 구 조 를 유지 해 야 합 니 다. 그러면 사용자 공간 과 커 널 공간 이 이 구 조 를 전달 할 때 복사 비용 이 3 대 socket 을 스 캔 할 때 선형 스 캔 을 할 수 있 습 니 다.
poll
poll 은 본질 적 으로 select 와 다 르 지 않 습 니 다. 사용자 가 들 어 온 배열 을 커 널 공간 으로 복사 한 다음 에 모든 fd 에 대응 하 는 장치 상 태 를 조회 합 니 다. 장치 가 준비 되 어 있 으 면 장치 대기 열 에 하 나 를 추가 하고 계속 옮 겨 다 닙 니 다. 모든 fd 를 옮 겨 다 니 고 준비 되 어 있 는 것 을 발견 하지 못 하면 현재 프로 세 스 를 걸 고 장치 가 준비 되 거나 주동 적 으로 시간 을 초과 할 때 까지 합 니 다.깨 어 난 후에 그것 은 다시 fd 를 옮 겨 다 닌 다.이 과정 은 여러 차례 무의미 한 역 사 를 겪 었 다.이것 은 최대 연결 수의 제한 이 없다. 이 유 는 링크 를 바탕 으로 저장 되 기 때문이다. 그러나 똑 같은 단점 이 있다. 대량의 fd 배열 은 사용자 상태 와 커 널 주소 공간 사이 에 전체적으로 복사 되 고 이런 복사 가 의미 가 있 든 없 든 간 에.poll 의 또 다른 특징 은 '수평 트리거' 입 니 다. fd 를 보고 한 후에 처리 되 지 않 으 면 다음 poll 에서 이 fd 를 다시 보고 합 니 다.
epoll
epoll 은 수평 트리거 와 가장자리 트리거 를 지원 합 니 다. 가장 큰 특징 은 가장자리 트리거 입 니 다. 프로 세 스 가 어떤 fd 가 방금 필요 한 상태 로 변 했 는 지 알려 주 고 한 번 만 알려 줍 니 다.앞에서 말 한 복사 문제 에 있어 서 epoll 은 mmap 를 사용 하여 복사 비용 을 줄 입 니 다.또 하나의 특징 은 epoll 이 '이벤트' 의 준비 알림 방식 을 사용 하고 epoll 을 통 해ctl 등록 fd, 이 fd 가 준비 되면 커 널 은 callback 과 유사 한 리 셋 체 제 를 사용 하여 이 fd, epoll 을 활성화 합 니 다.wait 알림 받 을 수 있 습 니 다.
select, poll, epoll 을 선택 할 때 구체 적 인 사용 장소 와 이 세 가지 방식 의 자체 특징 에 따라 야 합 니 다.겉으로 볼 때 epoll 의 성능 이 가장 좋 지만 연결 수가 적 고 연결 이 활발 한 상황 에서 select 와 poll 의 성능 은 epoll 보다 좋 을 수 있 습 니 다. 왜냐하면 epoll 의 알림 체 제 는 많은 함수 의 반전 이 필요 하기 때 문 입 니 다.
select
select 는 1983 년 에 4.2BSD 에 최초 로 나 타 났 습 니 다. 하나의 select () 시스템 호출 을 통 해 여러 파일 설명자 의 배열 을 감시 합 니 다. select () 가 돌아 오 면 이 배열 에 준 비 된 파일 설명자 가 커 널 에 의 해 표지 위 치 를 수정 하여 프로 세 스 가 이 문서 설명 자 를 얻 고 후속 적 인 읽 기와 쓰기 작업 을 할 수 있 습 니 다.
select 는 현재 거의 모든 플랫폼 에서 지원 되 고 좋 은 크로스 플랫폼 지원 도 그의 장점 이다. 사실은 지금 보면 이것 도 얼마 남지 않 은 장점 중 하나 이다.
select 의 단점 은 하나의 프로 세 스 가 감시 할 수 있 는 파일 설명자 의 수량 에 최대 제한 이 있다 는 것 이다. Linux 에 서 는 일반적으로 1024 이지 만 매크로 정 의 를 수정 하거나 커 널 을 다시 컴 파일 하 는 방식 으로 이 제한 을 높 일 수 있다.
또한, select () 가 유지 하 는 대량의 파일 설명 자 를 저장 하 는 데이터 구 조 는 파일 설명자 의 수량 이 증가 함 에 따라 복사 비용 도 선형 으로 증가 합 니 다.또한, 네트워크 응답 시간 지연 으로 인해 대량의 TCP 연결 이 비 활성 상태 에 있 지만, select () 를 호출 하면 모든 socket 을 선형 으로 스 캔 하기 때문에 비용 도 낭비 합 니 다.
상관 함수 및 구조 체
int select(int nfds, fd_set *restrict readfds,fd_set *restrict writefds, fd_set *restrict errorfds,struct timeval *restrict timeout);
void FD_CLR(int fd, fd_set *fdset); // fd_set
void FD_SET(int fd, fd_set *fdset); // fd_set
void FD_ZERO(fd_set *fdset); // fd_set 0
int FD_ISSET(int fd, fd_set *fdset); //
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
용례
#include
#include
#include
#include
#include
int main(void)
{
int fd;
fd_set rfds;
struct timeval tv;
int retval;
fd=open(...);
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.
");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.
");
exit(EXIT_SUCCESS);
}
poll
폴 은 1986 년 System V Release 3 에서 태 어 났 으 며, select 와 는 본질 적 으로 큰 차이 가 없 지만, 폴 은 최대 파일 설명자 수의 제한 이 없다.
poll 과 select 역시 하나의 단점 이 존재 합 니 다. 대량의 파일 설명 자 를 포함 하 는 배열 은 사용자 상태 와 커 널 의 주소 공간 사이 에 전체적으로 복 사 됩 니 다. 이 파일 설명자 가 준비 되 어 있 든 없 든 그 비용 은 파일 설명자 의 수량 이 증가 함 에 따라 선형 으로 증가 합 니 다.
또한, select () 와 poll () 은 준 비 된 파일 설명 자 를 프로 세 스에 알려 준 후 프로 세 스 가 IO 작업 을 하지 않 으 면 다음 에 select () 와 poll () 을 호출 할 때 이 파일 설명 자 를 다시 보고 하기 때문에 준 비 된 소 거 를 잃 지 않 습 니 다. 이 방식 을 수평 트리거 (Level Triggered) 라 고 합 니 다.
상관 함수 및 구조 체
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
struct pollfd {
int fd;
short events;
short revents;
};
POLLIN
#define POLLIN 0x0001 //
#define POLLRDNORM 0x0040 //
#define POLLRDBAND 0x0080 // 0
#define POLLPRI 0x0002 //
#define POLLOUT 0x0004 //
#define POLLWRNORM 0x0100 //
#define POLLWRBAND 0x0200 // 0
#define POLLERR 0x0008 //
#define POLLHUP 0x0010 //
#define POLLNVAL 0x0020 // -
timeout
-1
0
>0
용례
#include
#include
#include
#include
#include
#include
int main(void)
{
int fd1,fd2,ret;
struct pollfd pfd;
fd1=open(...);
fd2=open(...);
pfd.fd=fd1;
pfd.events=POLLIN;
pfd.fd=fd2;
pfd.events=POLLOUT;
ret=poll(&pfd, 2, 20);
if(ret<0){
printf("error!
");
}
if(ret==0){
printf("time out!
");
}
if(pfd.revents&POLLERR){
printf("error!
");
}
if(pfd.revents&POLLIN){
printf("POLLIN!
");
read(fd1,...);
}
if(pfd.revents&POLLOUT){
printf("POLLOUT!
");
write(fd2,...);
}
...
}
epoll
리 눅 스 2.6 에 이 르 러 서 야 커 널 이 직접 지원 하 는 실현 방법 이 나 타 났 다. 그것 이 바로 epoll 이다. 리 눅 스 2.6 에서 성능 이 가장 좋 은 다 중 I / O 준비 알림 방법 으로 인 정 받 고 있다.
epoll 은 수평 트리거 와 가장자리 트리거 (Edge Triggered) 를 동시에 지원 할 수 있 습 니 다. 프로 세 스 에 게 어떤 파일 설명자 가 방금 준비 상태 로 바 뀌 었 는 지 만 알려 줍 니 다. 만약 에 우리 가 행동 을 취하 지 않 았 다 면 다시 알려 주지 않 았 을 것 입 니 다. 이런 방식 을 가장자리 트리거 라 고 합 니 다. 이론 적 으로 가장자리 트리거 의 성능 은 더욱 높 지만 코드 실현 은 상당히 복잡 합 니 다.
epoll 역시 준 비 된 파일 설명자 만 알려 주 고 epoll 을 호출 할 때wait () 가 준 비 된 파일 설명 자 를 얻 었 을 때 실제 설명자 가 아니 라 준 비 된 설명자 의 수 를 나타 내 는 값 을 되 돌려 줍 니 다. epoll 이 지정 한 배열 에서 해당 수량의 파일 설명 자 를 순서대로 얻 으 면 됩 니 다. 여기 서도 메모리 맵 (mmap) 기술 을 사용 하여 이 파일 설명자 들 이 시스템 호출 시 복사 하 는 비용 을 철저히 줄 일 수 있 습 니 다.
또 다른 본질 적 인 개선 은 epoll 이 이벤트 기반 의 준비 알림 방식 을 사용 하 는 것 이다.select / poll 에서 프로 세 스 는 일정한 방법 을 호출 한 후에 만 커 널 에서 모든 감시 파일 설명 자 를 스 캔 할 수 있 으 며, epoll 은 사전에 epoll 을 통 해ctl () 은 파일 설명 자 를 등록 합 니 다. 파일 설명자 가 준비 되면 커 널 은 callback 과 같은 리 셋 체 제 를 사용 하여 이 파일 설명 자 를 신속하게 활성화 합 니 다. 프로 세 스 가 epoll 을 호출 할 때wait () 시 알림 받 기
epoll 은 두 가지 작업 방식 이 있 습 니 다. LT 와 ET:
LT (level triggered) 는 결 성 된 작업 방식 이 며, block 과 no - block socket 을 동시에 지원 합 니 다. 이 방법 에서 커 널 은 파일 설명자 가 준비 되 었 는 지 알려 주 고, 이 준 비 된 fd 에 대해 IO 작업 을 할 수 있 습 니 다.만약 당신 이 어떤 조작 도 하지 않 는 다 면, 커 널 은 계속 당신 에 게 알려 줄 것 입 니 다. 따라서, 이러한 모드 의 프로 그래 밍 은 오류 가 발생 할 가능성 이 적 습 니 다.전통 적 인 select / poll 은 모두 이런 모델 의 대표 이다.
ET (edge - triggered) 는 고속 작업 방식 으로 no - block socket 만 지원 합 니 다.이 모드 에서 설명자 가 준비 되 지 않 았 을 때 커 널 은 epoll 을 통 해 알려 줍 니 다.그 다음 에 파일 설명자 가 이미 준비 되 었 다 는 것 을 알 고 그 파일 설명자 에 게 더 많은 준비 알림 을 보 내지 않 을 것 이 라 고 가정 합 니 다. 어떤 작업 을 해서 그 파일 설명자 가 더 이상 준비 상태 가 되 지 않 을 때 까지 (예 를 들 어 요청 을 보 내 거나 받 거나 받 은 데 이 터 를 일 정량 보다 적 게 보 낼 때 EWOULBLOCK 오류 가 발생 합 니 다).그러나 이 fd 에 대해 IO 작업 을 계속 하지 않 으 면 커 널 은 더 많은 알림 (only once) 을 보 내지 않 습 니 다. 그러나 TCP 프로 토 콜 에서 ET 모드 의 가속 효용 은 더 많은 benchmark 확인 이 필요 합 니 다.
ET 와 LT 의 차 이 는 여기 서 나타 납 니 다. LT 이 벤트 는 버 리 지 않 고 buffer 에 데이터 가 있 으 면 사용자 가 읽 을 수 있 고 계속 알려 줍 니 다.ET 는 사건 발생 시 에 만 통지 합 니 다.LT 는 수평 트리거 이 고 ET 는 가장자리 트리거 로 간단하게 이해 할 수 있다.LT 모드 는 이벤트 가 처리 되 지 않 으 면 트리거 되 고 ET 는 고저 레벨 변환 시 (즉 상태 가 1 에서 0 또는 0 에서 1) 트리거 됩 니 다.
상관 함수 및 구조 체
용례
int epoll_create (int size) // epoll
int epoll_ctl (int epfd, int op, int fd,struct epoll_event *event); //
int epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout); // IO
int epoll_pwait (int epfd, struct epoll_event *events,int maxevents, int timeout); // IO
struct epoll_event{
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
typedef union epoll_data{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
#define EPOLL_CTL_ADD 1 //
#define EPOLL_CTL_DEL 2 //
#define EPOLL_CTL_MOD 3 //
EPOLLIN = 0x001, //
EPOLLPRI = 0x002, //
EPOLLOUT = 0x004, //
EPOLLRDNORM = 0x040,
EPOLLRDBAND = 0x080,
EPOLLWRNORM = 0x100,
EPOLLWRBAND = 0x200,
EPOLLMSG = 0x400,
EPOLLERR = 0x008, //
EPOLLHUP = 0x010, //
EPOLLRDHUP = 0x2000,
EPOLLONESHOT = (1 << 30), //
EPOLLET = (1 << 31) //