기본 콘텐츠로 건너뛰기

I/O - epoll

epoll 은 감시해야 하는 fd가 많을 때 select나 poll에 비해 성능이 좋다.

epoll_create() epoll 인스턴스를 생성, 이 인스턴스를 참조하는 fd를 리턴한다.
epoll_ctl() 관심 목록 설정할때 사용. 새 fd를 추가 하거나 기존 목록에서 제고 할 수 있고 이벤트 감시를 변경 할 수 있다.
epoll_wait() 인스턴스에서 준비 목록을 리턴한다.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "sys/epoll.h"
int epoll_create( int size );
// 성공하면 fd 리턴, 에러가 발생하면 -1
// 리눅스 2.6.8이전에는 커널에게 초기 데이터 구조체를 어떻게 설정하는지에 대한 거였다는데..... 이제는 필요 없단다
int epoll_create1() // 대신 이게 새로 생김
int epoll_ctl( int efd, int op, int fd, struct epoll_event* ev );
// 성공하면 fd 리턴, 에러가 발생하면 -1
// fd에는 pipe, pifo, socket, posix message queue, inotify instanc, divice, 다른 epoll 디스크립터등..이 될 수 있다.
// 만약 안되는놈을 지정하면 EPERM 에러를 발생 한다.
struct epoll_event {
    uint32_t events;
    epoll_data_t data;
}
typedef union epoll_data {
    void* ptr;
    int fd;
    uint32_t u32;
    uint64_t u64;
} epoll_data_t;
/** /proc/sys/fs/epoll 디렉토리에 있는 max_user_watches 에서 한도값을 확인 하고 수정 할 수 있다.**/


op 인자에 추가되는 flag
 EPOLL_CTL_ADD
 fd 를 epfd의 관심 목록에 추가, 이미 목록에 존재한다면 EEXIST 에러를 발생 시킨다.
 event 집합은 *ev에 저장 된다.
 EPOLL_CTL_MOD
 *ev에 지정된 정보를 이용해 fd 설정 변경. 관심 목록에 없는 fd라면 ENOENT 에러를 발생 시킨다.
 EPOLL_CTL_DEL
 epfd 에서 fd를 제공 한다. epfd 관심 목록에 없는 fd를 제거하려면 ENOENT 에러를 발생 한다.
 fd를 닫으면 epoll 관심 목록에서 자동 제거 된다.


?
1
2
3
4
5
6
7
8
9
10
11
12
#include "sys/epoll.h"
int epoll_wait( int epfd, struct epoll_event* evlist, int maxevents, int timeout );
// 성공하면 준비된 fd count를 리턴 한다.
// 타임 아웃이면 0, 에러면 -1을 리턴
// 준비된 fd는.. evlist가 가리키는 epoll_event구조체 배열로 리턴됨.
// timeout 이 -1이면 epfd의 관심 목록에 있는 fd중 하나에서 이벤트나 시그널이 발생할때까지 블럭
// timeout 이 0이면 epfd에서 현재 이용 할 수 있는 fd가 있는지를 비블로킹 방식으로 검사
// timeout이 0보다 크면, epfd중 fd하나에서 이벤트나 시그널이 발생할때까지 timeout 밀리초만큼 블록 한다.
//** 멀티쓰레드에서 한 쓰레드는 epoll_wait 하고 있고 다른 스레드에서 epoll_ctl을 수행해 epfd에 add할 경우, **//
//**  새로 추가된 fd가 바로 적용된다. epoll_wait는 새로 추가된 fd의 준비 여부를 리턴 결과에 포함 한다. **//


비트
설명
EPOLLIN
높은 우선순위 데이터 외의 데이터를 읽을 수 있다.
EPOLLPRI
높은 우선순위 데이터를 읽을 수 있다
EPOLLRDHUP상대편 소켓 셧다운
EPOLLOUT일반 데이터를 기록 할 수 있다
EPOLLET 에지 트리거 이벤트 통지를 적용
EPOLLONESHOT
 이벤트 통지 뒤에 감시를 비활성화 한다.
EPOLLERR에러 발생
EPOLLHUP장애 발생 (hangup)



하늘색은 EPOLL_CTL의 입력, WAIT 리턴 둘다 사용
주황색은 CTL의 입력에서만 사용
회색은 WAIT 리턴에서만 사용

EPOLLONESHOT
기본적으론 epoll_ctl로 관심목록에 추가하면 제거할때까지 활성 상태로 남게 된다.
특정 fd로부터 통지를 받으려면 ev.ents값에 EPOLLONESHOT 를 지정하면 됨. 지정하고 wait를 호출하며 해당 fd가 ready상태인지 알려준뒤 해당 fd를 비활성화가 되고 이후에 다시 wait를 호출하면 비활성화된 fd는 안알려준다. (필요할 경우 EPOLL_CTL_MOD 를 사용해 재활성화 해야 함. )


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "sys/epoll.h"
void epoll( const char* pName )
{
    int epCnt = 10;
    epfd = epoll_create( epCnt );
    if ( -1 == epfd ) return;
    for ( int i = 0; i < 5; ++i ) {
        int fd = open( pName, O_RDONLY );
        if ( -1 == fd ) return;
        printf("Opened : %s, fd %d\n", pName, fd );
        struct epoll_event event;
        event.events =  EPOLLIN;
        ev.data.fd = fd;
        if ( -1 == epoll_ctl( epfd, EPOLL_CTL_ADD, fd, &event ) )
            return;
        while ( epCnt - 1 > 0 ) {
            printf("About to epoll_wait\n");
            // 한번에 처리 가능한 이벤트 갯수
            const int MAX_EVENTS = 5;
            struct epoll_event eventList[ MAX_EVENTS ];
            int ready = epoll_wait( epfd, MAX_EVENTS, -1 );
            if ( -1 == ready ) {
                if ( EINTR == errno )
                    continue; // 시그널에 의해 중단되면 실행 재개
                else
                    return; // 준비된 fd 없음..
            }
            printf("Ready : %d\n", ready );
            for ( int eventIndex = 0; eventIndex < ready; ++eventIndex ) {
                printf("fd %d, EPOLLIN? %s, EPOLLHUP? %s, EPOLLERR? %s\n",
                    eventList[ eventIndex ].data.fd,
                    eventList[ eventIndex ].events & EPOLLIN ? "true" : "false",
                    eventList[ eventIndex ].events & EPOLLHUP ? "true" : "false",
                    eventList[ eventIndex ].events & EPOLLERR ? "true" : "false"
                    );
            }
            if ( eventList[ eventIndex ].events & EPOLLIN ) {
                int s = read( eventList[ eventIndex ].data.fd, buf, 1024 );
                if ( -1 == s ) return; // 읽기 에러
                printf("reaad %d bytes : %s\n", s, buf );
            }
            else
            {
                printf("closing fd %d\n", eventList[ eventIndex ].data.fd );
                if ( -1 == close( eventList[ eventIndex ].data.fd ))
                    return;
                --epCnt;
            }
        }
    }
    printf("All file descriptors closed; bye\n");
}


댓글

이 블로그의 인기 게시물

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 개의...

시리얼(Serial) 이란?

출처 - http://www.ni.com/white-paper/2895/ko/#toc4 시리얼은 거의 모든 PC에서 표준으로 사용되는 디바이스 통신 프로토콜입니다. 시리얼의 개념을 USB의 개념과 잘 구분하십시오. 대부분의 컴퓨터에는 2개의 RS232 기반 시리얼 포트가 있습니다. 시리얼은 또한 여러가지 디바이스에서 계측을 위한 일반 통신 프로토콜이며, 여러 GPIB 호환 디바이스에는 RS232 포트가 장착되어 있습니다. 뿐만 아니라, 원격 샘플링 디바이스로 데이터 수집을 하는 경우에도 시리얼 통신을 사용할 수 있습니다. 시리얼 통신의 개념은 간단합니다. 시리얼 포트는 정보의 바이트를 한번에 한 비트씩 순차적으로 송수신합니다. 한번에 전체 바이트를 동시에 전달하는 병렬 통신과 비교하면 시리얼 통신은 속도가 느리지만 훨씬 간단하며 장거리에도 사용할 수 있습니다. 예를 들어, 병렬 통신용 IEEE 488 스펙을 보면 기기간 케이블링은 총 20 m 미만이어야 하며, 두 개의 디바이스간은 2 m 미만이어야 합니다. 반면 시리얼 통신은 최대 1.2 Km의 통신거리를 보장합니다. 통상 엔지니어들은 ASCII 데이터를 전송할 때 시리얼 통신을 사용합니다. 이 때 송신용 (Tx), 수신용 (Rx), 그라운드용 (GND)의 세 가지의 전송 라인을 사용하여 통신합니다. 시리얼은 비동기식이므로 포트는 한 라인에서 데이터를 전송하고 다른 라인에서 데이터를 수신합니다. 핸드쉐이킹용 라인도 사용 가능하지만 필수 요구사항은 아닙니다. 시리얼 통신의 가장 중요한 특징에는 보드 속도 (baud rate), 데이터 비트, 정지 비트, 패리티가 있습니다. 두 개의 포트가 통신하기 위해서는 이러한 파라미터가 반드시 적절하게 맞춰져야 합니다. 보드 속도는 통신의 속도를 측정하는 수치이며 초당 비트 전송 숫자로 표시됩니다. 예를 들어 300 보드 속도는 초당 300 비트를 의미합니다. 엔지니어들이 흔히 말하는 클럭 주기는 보드 속도를 의미합니다. 따라서 프로토콜에 ...

IR Cut Filter

R필터는 IR Cut off Filter, 적외선 차단 필터라고도 하며 이미지 센서라는 디지털 영상 장치의 핵심 부품의 작용 원리 때문에 필요한 부품임. 렌지를 통해 들어오는 빛은 일반적으로 인간의 눈으로 구별할 수 있는 가시광선 뿐 아니라 구별할 수 없는 적외선도 들어옴. 빛의 파장은 나노미터(nm)단위로 표시하는데 1nm는 10억분의 1미터, 즉 10-9승m로 이미지 센서는 가시광선 영역인 400~700nm뿐 아니라 근적외선 영역(~1150nm)까지 감지하여, 실제 색이나 화상하고는 관계없는 신호로 인해 영상의 선명도와 해상도가 떨어지므로 근적외선 영역의 파장들을 제거해 주기 위해 IR Cut off Filter가 필요함. 2. IR필터의 구조 및 제조과정 IR필터의 구조는 유리기판, 즉 D263과 같은 glass 위에 굴적률이 다른 두 가지 물질 Ti02, Si02 혹은 Ta205, Si02 같은 물질들을 교대로 증착시켜서 가시광선 영역은 투과하고 근적외선 영역은 반사시키는 구조임. IR터의 제조과정을 살펴보면 이들을 만드는 데 있어서 핵심기술은 진공박막증착 기술이며, 이는 유리 기판에 굴절률이 서로 다른 2가지 물질, Ti02/Si02혹은 Ta205/Si02을 교대로 증착시켜서 (30~40층) 가시광선 영역을 투과하고 근적외선 영역은 반사시키는 광학필터를 만드는 것임.  과거에는 유리 기판 대신에 LCD유리를 많이 사용했으나 최근 화소스가 증가하면서 규격이 높아져서 D263이라는 양면 연마된 유리 기판들이 많이 쓰이고 있음. 이들 제품은 우선 투과 및 반사대역이 원하는 파장대역과 맞는가 하는 점과 표면에 일정 크기 이상의 이물들이 없는 가의 평가법을 통한 평가를 통해 제잭된 필터 원파(보통 127X127mm)을 필요한 크기로 잘라서 CCD나 CMOS등의 이미지 센서 앞에서 장착하게 됨. 3. IR필터 응용분야 IR필터는 주로 디지털 카메라, 캠코더, CCTY용 카메라, 적외선 감시카메라, 차량용 후방감시 카메라 등 다양한 분야에 사용되나 최근 이...