《 Linux 시스템 프로 그래 밍 》 노트 제4 장 (2)
4.2 이벤트 폴 인터페이스
제2 장 - I / O 다 중 재 활용 기술 을 배 울 때 select () 와 poll () 두 시스템 호출 을 언급 했 습 니 다. 이 두 시스템 호출 은 여러 파일 설명자 에 막 혀 CPU 자원 을 양보 하고 해당 하 는 파일 의 읽 기, 쓰기 가 완료 되 거나 이상 이 발생 하 는 것 을 막 을 수 있 습 니 다.그러나 상기 두 시스템 호출 은 모두 잠재 적 인 문제 (구체 적 으로 대응 하 는 장 참조) 가 있 고 커 널 2.6 이후 epoll () 체 제 를 도입 하여 전에 언급 한 문 제 를 해결 하고 변두리 트리거 체 제 를 도입 했다.I / O 다 중 복용 모델 에서 epoll () 은 현재 가장 좋 은 방안 이다.
4.2.1 새로운 epoll 인 스 턴 스 생 성
epoll 인 스 턴 스 를 만 드 는 것 은 epoll 모델 을 사용 하 는 첫 번 째 단계 입 니 다.
#include <sys/epoll.h>
int epoll_create(int size);
이 함수 가 새 epoll 파일 설명 자 를 열 고 되 돌려 줍 니 다. 다음 epoll 작업 은 이 파일 설명자 로 진행 되 어야 합 니 다.매개 변수 size 는 원래 되 돌아 오 는 epoll 파일 설명자 가 초기 에 몇 개의 파일 설명 자 를 감청 할 수 있 는 지 지정 하 는 데 사용 되 었 으 나 Linux 커 널 은 감청 가능 한 파일 설명자 수 를 동적 으로 증가 시 킬 수 있 기 때문에 이 매개 변 수 는 새로운 커 널 버 전에 서 무 시 됩 니 다.2.6.27 커 널 버 전에 새로운 시스템 호출
int epoll_create1(int flags);
을 도입 하 였 으 며, 그 역할 은 epoll 입 니 다.create () 와 마찬가지 로 인자 flags 는 새 epoll 파일 설명자 의 속성 을 표시 합 니 다. 현 재 는 EPOLL_CLOEXEC
만 지원 합 니 다.이 호출 은 성공 할 때 epoll 파일 설명자 의 값 을 되 돌려 줍 니 다. 실패 할 때 - 1 을 되 돌려 주 고 errno 를 설정 합 니 다.주의해 야 할 것 은 epoll 파일 설명자 도 시스템 자원 을 차지 하기 때문에 더 이상 사용 하지 않 을 때 close () 를 호출 하여 닫 아야 합 니 다.파일 설명자 와 마찬가지 로 epoll 자원 에 대응 하 는 모든 파일 설명자 가 닫 혔 을 때 커 널 은 해당 하 는 자원 을 시스템 에 되 돌려 줍 니 다.4.2.2 제어 epoll
epoll 인 스 턴 스 를 만 든 후에 우 리 는 되 돌아 오 는 파일 설명 자 를 사용 하여 어떤 파일 설명자 와 어떤 사건 을 감청 하 는 지 제어 할 수 있 습 니 다.
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
처리 성공 시 0 을 되 돌려 주 고 실패 시 - 1 을 되 돌려 주 며 errno 를 설정 합 니 다.epfd - 열 린 epoll 파일 설명자 op - epfd 와 fd 에 대해 무엇 을 합 니까?
값 을 얻다
속뜻
EPOLL_CTL_ADD
fd 를 epfd 의 관심 목록 [^ 1] 에 추가 합 니 다. 즉, fd 를 감청 하고 감청 사건 은 이벤트 매개 변수 에서 설명 합 니 다.fd 호출 을 반복 하면 EEXIST 오류 가 발생 합 니 다.
EPOLL_CTL_MOD
관심 목록 의 fd 에 대응 하 는 epollevent 는 이벤트 매개 변수 로 덮어 씁 니 다. 존재 하지 않 는 fd 를 수정 하면 ENOENT 오류 가 발생 합 니 다.
EPOLL_CTL_DEL
fd 를 epfd 의 관심 목록 에서 제거 하고 이벤트 매개 변 수 는 무시 합 니 다.fd 가 close () 되 었 을 때 epfd 의 관심 목록 이 자동 으로 이동 합 니 다.존재 하지 않 는 fd 를 제거 할 때 ENOENT 오류 발생
fd - 작 동 할 파일 설명자, 대응 하 는 파일 은 FIFO, Socket, 파이프 일 수 있 습 니 다.메시지 큐, 터미널 등 이지 만 일반 파일 이나 디 렉 터 리 일 수 없습니다. 그렇지 않 으 면 EPERM 오류 가 발생 했 습 니 다.이벤트 - 감 청 된 이벤트 정보 와 사용자 데이터 struct 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_data_t data; /* */
};
이벤트 대표 감청 이벤트 유형
값 을 얻다
속뜻
EPOLLERR
파일 오류, 이 사건 은 기본적으로 감청 되 었 습 니 다.
EPOLLET
다른 로고 와 작업 하거나 연산 하여 가장자리 트리거 를 엽 니 다.
EPOLLHUP
파일 이 걸 려 있 습 니 다. 이 사건 은 기본적으로 감청 되 었 습 니 다.
EPOLLIN
파일 작성 완료
EPOLLONESHOT
다른 표지 와 연산 을 하거나 한 번 감청 이 완 료 된 후 이 파일 설명 자 는 감청 되 지 않 습 니 다.EPOLL 을 사용 하지 않 는 한CTL_MOD 가 감청 사건 을 다시 설정 합 니 다.
EPOLLOUT
파일 작성 완료
EPOLLRDHUP
socket 통신 중 엔 드 닫 기
EPOLLPRI
높 은 우선 순위 외부 데이터 읽 을 수 있 습 니 다.
epoll_data 는 유 니 온 형식의 데이터 입 니 다 [^ 2].사용자 정의 정 보 를 저장 하 는 데 사 용 됩 니 다. 파일 설명자 가 준비 되면 이 데 이 터 는 사용자 에 게 되 돌아 갑 니 다. 감청 된 파일 설명 자 를 epoll 에 할당 하 는 것 이 자주 사 용 됩 니 다.event.data.fd。또한 안전 을 보장 하 는 전제 에서 처리 함수 의 주 소 를 ptr 에 할당 할 수 있 습 니 다.epoll_ctl () 은 관심 있 는 파일 설명자 와 감청 이 벤트 를 커 널 공간 으로 복사 합 니 다. 한 번 만 호출 하면 됩 니 다. 매번 select () 와 poll () 호출 은 파일 설명자 정 보 를 커 널 로 복사 해 야 합 니 다.epoll 때문에ctl () 에 추 가 된 파일 설명 자 는 커 널 공간 을 차지 하기 때문에 리 눅 스 는 감청 파일 설명자 의 최대 수량 을 규정 하고 파일
/proc/sys/fs/epoll/max_user_watches
에 규정 합 니 다.4.2.3 epoll 이벤트 대기
epoll 인 스 턴 스 를 만 들 고 epoll 감청 파일 설명자 와 이 벤트 를 수정 한 후에 파일 설명자 가 준비 되 기 를 기다 리 는 진정한 차단 입 니 다.
#include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epoll_wait () 는 epfd 를 기다 리 는 관심 목록 의 파일 과 이벤트 준 비 를 막 을 수 있 습 니 다. 시간 초과 시간 은 timeout 밀리초 입 니 다.시간 이 초과 되 지 않 아 파일 이 준비 되 지 않 으 면 준 비 된 파일 의 개 수 를 되 돌려 주 고 이벤트 에 정 보 를 저장 합 니 다.이 벤트 는 사용자 가 자체 적 으로 신청 한 배열 입 니 다. 내용 은 epoll 입 니 다.ctl () 시 설정 한 정보 입 니 다. 최대 요 소 는 maxevents 에서 지정 합 니 다. 즉, 한 번 에 최대 몇 개의 파일 이 준비 되 었 는 지 알려 줍 니 다.timeout 인 자 는 0 일 때 이 호출 이 막 히 지 않 고 조회 후 즉시 돌아 갑 니 다.위 - 1 시 는 시간 을 초과 하지 않 았 음 을 나타 낸다.오류 가 발생 했 을 때 - 1 을 되 돌려 주 고 errno 를 설정 하 며 시간 을 초과 하여 0 을 되 돌려 줍 니 다.
정확 한 용법 은 epollwait () 반환 후 반환 값 을 판단 합 니 다. 반환 값 이 0 이상 이면 이벤트 배열 을 옮 겨 다 니 며 이벤트 유형 과 fd 에 따라 처리 합 니 다.이 제 는 epoll () 과 select () / poll () 의 비교 우 위 를 볼 수 있 습 니 다. epoll () 은 파일 이 준 비 된 후에 우리 만 관심 을 가 져 야 할 파일 설명자 의 집합 을 제공 합 니 다. 뒤의 두 가지 처럼 모든 파일 설명 자 를 옮 겨 다 니 며 어떤 파일 이 준비 되 었 는 지 확인 하지 않 아 도 됩 니 다.다음 코드 는 표준 입력 에서 데이터 가 준비 되 고 읽 기 를 기다 리 는 것 을 보 여 줍 니 다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/epoll.h>
#define MAX_EVENTS 3
int main (void)
{
int nr_events, epfd;
epfd = epoll_create(MAX_EVENTS);// ,epoll
//
struct epoll_event events[MAX_EVENTS] = {};
struct epoll_event evt;
//
evt.events = EPOLLIN;
evt.data.fd=STDIN_FILENO;
int iRet = epoll_ctl(epfd, EPOLL_CTL_ADD, evt.data.fd, &evt);
if(iRet == -1)
{
perror("epoll_ctl");
return -1;
}
//
nr_events = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (nr_events < 0)
{
perror("epoll_wait");
return -1;
}
for (int i = 0; i < nr_events; i++)
{
char temp[1024] = {0};
iRet = read(events[i].data.fd, temp, sizeof(temp));
printf("event=%ld on fd=%d,data:%s
", events[i].events, events[i].data.fd, temp);
}
}
파일 이 준비 되 기 를 기다 리 는 동안 신 호 를 받 았 습 니 다. epollwait () 는 오류 코드 EINTR 을 되 돌려 줍 니 다.이 때 는 epoll 을 다시 호출 하면 됩 니 다.wait (), 위의 프 리 젠 테 이 션 코드 는 특별한 처 리 를 하지 않 았 습 니 다.
또한 다 중 스 레 드 장면 에서 하나의 스 레 드 는 epoll 에 있 습 니 다.wait () 와 동시에 다른 스 레 드 에서 파일 설명 자 를 수정 할 수 있 습 니 다. 수정 은 즉시 유효 하 며 epoll / 에 영향 을 줄 수 있 습 니 다.wait()。테스트 코드 는 다음 과 같 습 니 다:
// -lpthread, pthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <unistd.h>
#define MAX_EVENTS 3
void *thrd_func(void *arg);
int epfd;
int main()
{
pthread_t tid;
int *thread_ret = NULL;
int nr_events;
epfd = epoll_create(MAX_EVENTS);
struct epoll_event events[MAX_EVENTS] = {};
if (pthread_create(&tid,NULL,thrd_func,NULL)!=0)
{
printf("Create thread error!
");
exit(1);
}
//
// epoll
nr_events = epoll_wait(epfd, events, MAX_EVENTS, -1);
if (nr_events < 0)
{
perror("epoll_wait");
return -1;
}
// ,epoll_wait()
printf("event=%ld on fd=%d,can write!
", events[0].events, events[0].data.fd);
pthread_join(tid, (void**)&thread_ret );
return 0;
}
void *thrd_func(void *arg)
{
struct epoll_event evt;
// ,
evt.events = EPOLLOUT;
evt.data.fd=STDOUT_FILENO;
sleep(3);// 3
printf("add fd!
");
int iRet = epoll_ctl(epfd, EPOLL_CTL_ADD, evt.data.fd, &evt);
if(iRet == -1)
{
perror("epoll_ctl");
}
pthread_exit(NULL);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Linux Shell 프로 그래 밍 - 텍스트 처리 grep, sed사용자 가 지정 한 '모드' 에 따라 대상 텍스트 를 일치 하 게 검사 하고 일치 하 는 줄 을 인쇄 합 니 다. ##포함 되 지 않 음, 역방향 일치 \ ##키워드 앞 뒤 가 맞지 않 고 키워드 만 일치 합 니 다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.