기본 콘텐츠로 건너뛰기

[C언어] select / poll / epoll example

* select()

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
FD_SET(int fd, fd_set *set); // fd를 set(검사대상)에 추가
FD_CLR(int fd, fd_set *set); // fd를 set에서 제거
FD_ZERO(fd_set *set);// set에 지정된 모든 대상 제거,select호출 전 항상 호출함
FD_ISSET(int fd, fd_set *set); //select()호출 후 fd가 사용 가능한지 확인 return bool

ex)
struct timeval tv;
fd_set readfds;
int ret;

FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);

tv.tv_sec = 0;
tv.tv_use = 500;
ret = select (STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);

if(FD_ISSET(STDIN_FILENO, &readfds)){ /* 'fd' is readable without blocking! */ }

* poll()

#include <sys/poll.h>

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

struct pollfd {
int fd; /* file descriptor */
short events; /* requested events to watch */
short revents; /* returned events witnessed */
};

ex)

struct pollfd fds[2];
int ret;

fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;

fds[1].fd = STDOUT_FILENO;
fds[1].events = POLLOUT;

ret = poll(fds, 2, TIMEOUT);

if(fds[0].revents & POLLIN){ /* stdin is readable */ }
if(fds[0].revents & POLLOUT){ /* stdout is writable */ }

poll() vs select()

poll  select 

매개변수에 +1(FILENO+1)이 필요없다   

fd의 숫자가 큰 경우 select보다 효율적  fd_set값이 크면 비효율적이다. 
bitmask를 모두 검사하며 특히 bit가 분산된 경우 더욱 비효율적이다 
매번 set을 초기화해야 한다.(FD_ZERO)
이식성을 높이기 위해 timeout parameter(timeval)를 매번 초기화 해야함

몇몇 UNIX에서는 poll을 지원하지 않는다 이식성이 높다
    microsecond단위까지는 timeout resolution이 더 좋다

*epoll()

Epoll(Event Poll): poll()과 select()를 개선한 형태

2.6 Linux kernel 이후부터 사용 가능
select()/poll()은 호출될 때마다 fdset을 모두 확인하나 epoll은 실제 감시작업과 감시 등록작업을 분리하는 방법으로 이런 문제를 해결.

#include <sys/epoll.h>

int epoll_create(int size)

// size는 감시대상의 개수를 알려주는 힌트이며 정확한 수를 요구하지는 않는다.
// return value : file descriptor or error(-1)
// file descriptor는 poll이 끝난 다음 close()를 이용하여 닫아야 한다.

ex)
int epfd;

epfd = epoll_create(100);
if(epfd < 0) // errorclose(epfd);
int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
struct epoll_event{
__u32 events; /* events */
union {
void *ptr;
int fd;
__u32 u32;
--u64 u64;
}data;
};

// op parameter
// EPOLL_CTL_ADD : 감시대상에 fd 추가
// EPOLL_CTL_DEL : 감시대상에서 fd 제거
// EPOLL_CTL_MOD : 기존 등록된 fd의 event를 수정

ex)

struct epoll_event event;
int ret;

event.data.fd = fd;
event.events = EPOLLIN | EPOLLOUT;

ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
if(ret) //ERROR
event.data.fd = fd;
event.events = EPOLLIN;
ret = epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &event);
ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &event);

** EPOLL_CTL_DEL을 사용할 때 event를 NULL로 보내면 2.6.9이전 버전에서 호환성이 맞지 않는다.
event 매개변수의 events필드에 EPOLLET값을 설정하면, fd에 대한 감시가 레벨트리거에서 에지트리거로 바뀐다. 에지트리거는 일반적으로 비차단 입출력을 활용하도록 다른 프로그래밍 접근방식을 요구하므로(만약 read를 요청하는 시점에 읽을 수 있는 상태라고 해도 write가 진행중이면 write가 끝날 때까지 기다린다) EAGAIN을 주의깊게 검사해야 한다.

#include <sys/epoll.h>

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

ex)

#define MAX_EVENTS64

struct epoll_event *events;
int nr_events, i, epfd;

events = malloc (sizeof(struct epoll_event) * MAX_EVENTS);

nr_events = epoll_wait (epfd, events, MAX_EVENTS, -1);

if(nr_events < 0) 
{
free(events);
return 1; //ERROR
}
for(i =0; i < nr_events; I++) 
{
//events[i].events마다 events[i].data.fd에 대한 작업 진행가능
}
free(events);



댓글

이 블로그의 인기 게시물

UNIX C errno 정리( 에러 번호 )

#define EPERM   1   /* Operation not permitted      */ #define ENOENT  2   /* No such file or directory        */ #define ESRCH   3   /* No such process          */ #define EINTR   4   /* interrupted system call      */ #define EIO 5   /* I/O error                */ #define ENXIO   6   /* No such device or address        */ #define E2BIG   7   /* Arg list too long            */ #define ENOEXEC 8   /* Exec format error            */ #define EBADF   9   /* Bad file descriptor          */ #define ECHILD  10  /* No child processes           */ #define EAGAIN  11  /* Resource temporarily unavailable */ #define ENOMEM  12  /* Not enough space         */ #define EACCES  13  /* Permission denied            */ #define EFAULT  14  /* Bad address              */ #define ENOTBLK 15  /* Block device required        */ #define EBUSY   16  /* Resource busy            */ #define EEXIST  17  /* File exists              */ #define EXDEV   18  /* Improper link            */ #define ENODEV  19  /* No such

Baud Rate 와 Bit Rate 의 차이점

출처 - http://solvline.com/technical_info/tech_note_view.php?no=22&fno=&PHPSESSID=f5f096a5b1090ca017552de78745b8aa 1. Bit Rate 와 Baud Rate 의 정의 1.1 Bit Rate 정의 비트 레이트 (Bit Rate) 는 초당 얼마나 많은 데이터 비트 (‘1’ 또는 ‘ 0’) 를 전송할 수 있는가를 나타내는 말이다 . 또 우리가 자주 쓰는 BPS 라는 말이 있는데 이는 Bit Per Second 로서 초당 보낼 수 있는 비트의 수를 나타낸다 . 이는 모뎀의 전송속도를 측정하는 단위로 사용되어 졌다 . 일반적으로 28,800 모뎀이라면 28,800bps 의 전송속도를 나타내는 것이다 . 예를 들어 , 2400bit/second(bps) 라면 초당 2400 개의 비트 정보를 전달할 수 있다는 뜻이다 . 이는 반대로 이야기하면 1 비트 정보를 보내기 위해서 416.6us 의 시간 (1s/2400bit) 이 필요하다는 이야기이다 . 1.2 Baud Rate 보 레이트 (Baud Rate) 는 초당 얼마나 많은 심볼 (Symbol, 의미 있는 데이터 묶음 ) 을 전송할 수 있는가를 나타내는 말이다 . 이는 이론적인 통신 단위로 초당 신호 (Signal) 요소의 수 를 나타낸다 . 만약 하나의 신호요소가 2 비트로 구성되어 있는 경우라면 보는 BPS 의 반이 된다 . 즉 , 1 보 동안 2 비트가 전송된다 . 일반적으로 신호를 1 비트로 여긴다면 BPS 와 같은 단위가 된다 . 심볼이란 말은 의미 있는 데이터 비트의 묶음이다 . 일반적으로 시리얼 통신에서는 데이터 비트가 8-bit 를 사용하므로 이를 하나의 심볼이라고 이야기 할 수 있다 . 1 개의 symbol ( 또는 character) 는 8 개의 bit 정보와 같다 . 예를 들어 , 2400 baud rate 를 갖는다는 말은 1 초에 2400 개의

[C언어] epoll 설명

출처 -  http://biscuit.cafe24.com/moniwiki/wiki.php/epoll 1  준비 2  socket 프로그래밍 기본 3  비동기 입출력 (Asyncronous I/O) & 입출력 다중화 (I/O Multiplexing) 4  select 5  select 와  poll  그리고 epoll. 그 차이 6  epoll 프로그래밍 흐름 7  epoll 함수들 8  epoll References 빈폴도 아니고, 이폴이란 대체 무엇일까? 당신은 서버한대로 몇 명의 동시접속자를 수용할 수 있습니까? 최근에 인터넷에 떠돌아다니는  c10k_problem 은 대당 10K, 즉 1만명의 동시접속(concurrent users)을 받아보자는 문제다. 서버 프로그래밍을 해 본 사람이라면 이게 그리 만만한 문제가 아니라는 것을 직감할 듯 --; 요즘의 Massive 온라인게임은 '분산처리'가 기본이라 한 대에서 많은 이용자를 커버하기보다는 여러대가 하나의 세트로써 구성하는 것이 인기가 있고 다수의 커넥션보다는 소수 커넥션에서의 대용량 전송이 더 중요한 요소이기도 하다. c10k problem에 나또한 관심을 가지게 되었고, epoll 이 최근 급부상하는 솔루션으로 인기가 있다기에 한 번 파보자 하고 결심하고 이 글을 시작했다. 마침 wiki에도 관심이 있던 차라, wiki 공부도 할 겸해서 epoll 을 연구하는 과정을 이 wiki에 담아 보고자 한다. 1  준비  # * 누구를 위한 epoll 인가? epoll은 '한 대의 서버에서 아주많은 동시접속자를 처리하기 위한 수단'이다. 이미 당신이 그 수단을 알고 있다면 - epoll 이건 아니건 - 이 글은 별로 도움이 안될듯하다. 동시접속자가 천명을 넘지않는다면 구닥다리 방법을 이용하는 것과 큰 차이가 없으리라 본다. 또한, epoll은  Linux 프로그래머의 도구 이다. M$ wind