기본 콘텐츠로 건너뛰기

글

라벨이 epoll인 게시물 표시

EPOLL* == POLL*

Linux에서 사용할 수 있는 최고 MUX, epoll! 아흥~* 이것에 그냥 아주 녹아들어 살고 있다. 아주 좋아좋아~* 각설하고, 프로그래머라면 될 수 있으면 잘 설계한 소스 하나 가지고 여기저기 사골 울궈 먹듯 울궈 먹고 싶어할 것이다. 나 역시 그랬고, 기존 poll을 잘 씌운 클래스를 epoll로 포팅하려고 했다. 이때 문제점이 하나 있는데, 각 API에서 이벤트를 나타내는 변수를 POLL* 또는 EPOLL*로 처리하고 있다. 많이 쓰이는 녀석(IN, OUT, ERROR)은 대충 비슷해보이는데 말이야... 변환 없이 그냥 EPOLL에 POLL* 쓰면 혼날까? 결과적으론 EPOLL*랑 POLL*랑 동일한 녀석이다. 소스를 보자... #include <cstdio> #include <cstdlib> #include <typeinfo> using namespace std; #include <sys/poll.h> #include <sys/epoll.h> #define SHOWDEF(x) \ printf("%s(%s,%u): 0x%04X\n", #x, typeid(x).name(), sizeof(x), x) #define CMPDEF(x) \ printf("compare %s: %d\n", #x, POLL##x == EPOLL##x) int main(int,char**) { SHOWDEF(POLLIN); SHOWDEF(POLLPRI); SHOWDEF(POLLOUT); SHOWDEF(POLLERR); SHOWDEF(POLLHUP); SHOWDEF(EPOLLIN); SHOWDEF(EPOLLPRI); SHOWDEF(EPOLLOUT); SHOWDEF(EPOLLERR); SHOWDEF(EPOLLHUP); CMPDEF(IN); CMPDEF(PRI); CMPDEF(O...

epoll_ctl 오류

epoll_ctl를 이용하여, fd를 감시하라고 EPOLL_CTL_ADD한 뒤, 실수로 같은 fd를 또 추가하려고 한 경우 epoll_ctl은 EEXIST(File exists) 오류를 퉤!하고 뱉는다. 추가 되어 있지 않은 녀석을 EPOLL_CTL_MOD, EPOLL_CTL_DEL할 경우엔 ENOENT(No such file or directory) 오류를 퉤!하고 뱉는다. (드러운데 패버릴까?) 덧글: Linux Kernel 2.6.9 이전 버전은 EPOLL_CTL_DEL에 대해 네번째 인자를 반드시 요구하였지만, 이후 버전부터 삭제할 녀석에 대해 알고 싶지 않을 경우 네번째 인자를 NULL로 세팅해도 까칠하게 에러 뱉지 않는다. 원본 위치: http://purewell.egloos.com/3451855

ET와 LT

epoll에서 ET(Edge Triggered)와 LT(Level Triggered)는 무슨 차이일까? ET는 어떠한게 변경되었을 경우만 발생하며, LT는 변경해서 해소할 될 때까지 계속 발생한다. man 페이지에 있는 예를 좀 더 손쉽게 설명하자면... 파이프에 EPOLLIN을 건다. 파이프에 2K를 쓴다. epoll_wait 파이프에서 1K를 읽어온다. epoll_wait LT일 경우, 아직 파이프에 1K의 읽을 꺼리가 있기 때문에 5번 epoll_wait에서 이벤트를 검출할수 있다. 반면 ET는 읽을 꺼리와 상관 없이 파이프 버퍼 상태가 변동된 시점에서 딱 한 번 이벤트가 발생하기 때문에 3번 epoll_wait에서만 검출되고, 5번 epoll_wait에서는 검출되지 않는다. 원본 위치: http://purewell.egloos.com/3375379

epoll은 공평한가?

epoll은 공평할까? $man epoll... o Starvation ( Edge Triggered ): If there is a large amount of I/O space, it is possible that by trying to drain it the other files will not get processed causing starvation. This is not specific to epoll. The solution is to maintain a ready list and mark the file descriptor as ready in its associated data structure, thereby allowing the application to remember which files need to be processed but still round robin amongst all the ready files. This also supports ignoring subsequent events you receive for fd's that are already ready.... Edge Triggered에서 기아상태. 특별히 epoll에 국한된 문제는 아니라고 하는군. ㅡ_-)a 기본값은 Level Triggered이지만 정리하는 차원에서. #include <sys/types.h> #include <sys/socket.h> #include <sys/epoll.h> #include <iostream> #include <vector> #include <errno.h> #include <pthread.h> #include <sys/time.h> #include <signal.h> using namespace std; static long long getTimestamp(void) {     static struct tim...

fork는 epoll에서 감시하는 객체까지 복제하지 않는다.

리눅스 서버에서 epoll을 이용해서 event를 감시하면서 동시에 fork할 때는 주의가 아주매우많이 필요하다. 커널 소스를 직접 들여다 봐야하겠지만, 대략 시간이 없고 귀찮은 관계로 생략한다. 결론부터 말하자만 epoll_fd로 관리하는 감시할 이벤트 목록은 커널영역에 만들어지며, fork가 이를 복제하지 않기 때문에 부모 자식 간에 동일한 epoll_fd로 목록을 수정하면 인생 종치는거다. 자자... 말이 길었다. 대충 소스를 보도록 하자. #include <sys/epoll.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc,char* argv[]) {         const size_t epoll_size(1024);         int epoll_fd = epoll_create(epoll_size);         struct epoll_event ev;         memset(&ev, 0, sizeof(ev));         ev.events = EPOLLIN;         epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 0, &ev);         printf("%s\n", strerror(errno));         if (!fork())    ...