작성자 : 문경원 (imesu76@gmail.com)
작성일 : 2009년 02월08일
출처   : http://www.fsp21.org
참여 fsp21.org멤버 : 유영창, 이영민, 문경원 
                                                                                                                                    


1. exLib개요

exLib는 이벤트에 대한 처리에 도움을 주기 위해 개발한 라이브러리 입니다.

여기서 말하는 이벤트란 키보드 입력, 마우스 입력, 터치 스크린 입력등 입력 디바이스 드라이버를 통해 들어오는

입력을 통칭합니다.

약간의 감으로 느끼셨겠지면, 얼마전 gxlib를 이용하여 마우스 움직임을 화면에 표시하는 글을 올린적있음니다.

소스 부분을 보다 보면 poll을 이용하여 마우스 입력이 들어 왔을 때, 마우스 입력 이벤트 처리를 하는 부분이 있습니다.

즉 poll을 이용하며 입력 이벤트를 대기하기 위해 무한정 기다리지 않고, 이벤트가 발생한 시점에서 원하는 동작을 수행할 수 있습

니다.

예제1) 그냥 read 처리

while (1)
{
    read( fd, &buf, sizeof(input_event_t));                                    // mouse의 입력 값을 읽어 온다.   
    switch(buf.code)
    {
        case BTN_LEFT :     printf("왼쪽 버튼이 눌렸습니다.n");      break;
        case BTN_RIGHT :    printf("오른쪽 버튼이 눌렸습니다.n");    break;
        default :                break;
    }
    printf( "mouse read type:%x , cod:%x ,value:%xn", buf.type ,buf.code ,buf.value);     
   }
}

예제2) poll 함수를 이용한 read 처리

while (1)
{
    poll_state = poll(                                  // poll()을 호출하여 event 발생 여부 확인    
                      (struct pollfd*)&poll_events,     // event 등록 변수                     
                                                 1,     // 체크할 pollfd 개수
                                              1000      // time out 시간

                       );
    if ( 0 < poll_state)                                 // 발생한 event 가 있음
    {    
         if ( poll_events.revents & POLLIN)              // event 가 자료 수신
         {
            read( fd, &buf, sizeof(input_event_t));        // mouse의 값을 읽어 온다.
            switch(buf.code)
            {
                case BTN_LEFT :    printf("왼쪽 버튼이 눌렸습니다.n");   break;
                case BTN_RIGHT:    printf("오른쪽 버튼이 눌렸습니다.n"); break;
                default :          break;
            }
            printf( "mouse read type:%x , cod:%x ,value:%xn", buf.type,buf.code,buf.value);    
         }
         else if ( poll_events.revents & POLLERR)      // event 가 에러?
         {
            printf( "마우스 입력에 에러 발생  프로그램 종료");
            break;
         }
      }
   }
   close( fd);
   return 0;
}

예제1) ,2) 의 차이점이 느껴지시나요? 필을 느껴보세요. 

차이를 못느끼셨다면 요건 숙제로 하겠습니다. emoticon

장길석님의 poll에 대한 부분을 읽어 보시면 쉽게 알 수 있을거에요.

exLib는 요렇게 poll을 보다 쉽게 이용하고, 입력 드라이버에서 받아온 이벤트를 보다 쉽게 처리하기 위해 제공할

라이브러리 입니다.

이번 강좌에서는 우선 exlib 의 단독적인 사용법을 기술 하고,

조만간 exLib 와 gxLib의 환상적인 하모니 조합을 이용한 샘플 코드도 추가 하겠으니 기대하세요.

추가적으로 현재 www.fsp21.org에서 공동작업으로 개발하고 있는 입력 처리 라이브러이 ixLib의 기술 문서가

완료 되는 대로 exLib + ixLib + gxLib의 조합으로 보다 쉽게 입력 장치를 핸들링 할 수 있는 편리함을 제공하겠습니다.

기대 하세요. 

버젼은 아직 내지 않았고, fsp21 멤버들과 협의하여 버젼을 완성되면 다시 올리겠습니다.

오늘은 그냥 파일 압축한 날짜로 압축해서 올립니다.

우선은 exLib를 함수 소개 및 설치법, 샘플 소스에 대한 설명으로 오늘의 강의를 진행 하겠습니다.


                                                                                                                                                                     

1.1. exLib의 특징

  •  쉬운 설치
    별도의 다른 프로그램의 설치 가 필요 없고 , exLib소스를 참조하는 것 만으로 사용 가능
  •  모든 이벤트에 대해 동일한 처리 인터페이스 제공
  •  무료로 제공
    Fsp21 또는 FALinux Forum회원이라면 누구나 개발에 동참 할 수 있으며, 회원이 아니더라도 exLib가 제시한 저작권만 유의한다면 무료로 사용 가능
                                                                                                                                                                      

1.2. exLib의 기능

  • 파일 디스크립터 등록 기능
  • 입출력 발생치 처리 함수(read, writ)함 수 등록 기능
  • 등록된 파일 디스크립터 관리 기능

                                                                                                                                                                      

1.3. exLib의 저작권
라이브러리 소스별로 입력어 있는 상단의 주석을 변경 하지 않는 이상, 무료로 사용이 가능하며 배포도 가능합니다. 개발자와 개발 정보를 알려 주는 상단의 주석문을 절대 변경하지 마십시요.


                                                                                                                                                                     
2. exLib 설치 방법

다음의 웹사이트에서 소스를 다운로드 받으시면 됩니다. 

다운로드 받으신 후 압축을 해제하고 샘플을 실행시키시면 됩니다.

[imesu@localhost ]$ tar zxvf  exlib.tar.gz
[imesu@localhost exlib]$cd exlib
[imesu@localhost exlib]$make sample

복잡하게 생각 하지 마시고 압축 푼 다음에 디렉토리를 보면 아래와 같은 파일들이 있습니다.

[imesu@localhost exlib]$ ls
Makefile  ex.h  ex.c   sample_input_main.c  sample_main.c  test_main.c

[imesu@localhost exlib]$ make sample
Compiling sample_main.c ...
arm-linux-gcc -c  -I. -I/usr/arm-linux/include -Wall -O2 -g -o sample_main.o sample_main.c
arm-linux-gcc -I. -I/usr/arm-linux/include -Wall -O2 -g  sample_main.o ex.o -o sample_main
arm-linux-nm sample_main > sample_main.map
cp sample_main /nfs/exlib/sample_main

[imesu@localhost exlib]$ make input
arm-linux-gcc -I. -I/usr/arm-linux/include -Wall -O2 -g  sample_input_main.o ex.o -o sample_input_main
arm-linux-nm sample_input_main > sample_input_main.map
cp sample_input_main /nfs/exlib/sample_input_main


요렇게 arm용으로 컴파일 된 실행 파일을 얻을 수 있습니다. 보드(저희는 ez-2440 보드 사용했습니다) 를 nfs로 연결하시고 

타겟 보드에서 TEST 하시면 됩니다.

타겟 보드가  없는 분은 makefile을 약간 변경해서 gcc로 컴파일 한 후 pc에서 test 하셔도 됩니다.

makefile 수정하는 부분은 주변 궁금하신분 있음면 요청하시면 예시를 추후에 추가 하겠습니다. emoticon


                                                                                                                                                                     

3. exLib 함수설명

3.1. ex_init() 초기화

  • 설명  :
    event 라이브러리를 초기화한다..

헤더

ex.h

형태

int      ex_init( int wait_time )

인수

wait_time poll 대기 시간 설정, 단위[ms], 0이상의

반환

-

주의

-

  • 예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c의 일부분 입니다.

 if(ex_init( 30))
 {
         ex_print_error("\n");
         exit(0);
 }

                                                                                                                                                                     
3.2. ex_print_error ()  에러메시지 표시 함수

  • 설명  :
    exlib에 에러코드, 에러문자열 및 사용자 메세지 출력합니다.

헤더

ex.h

형태

int      ex_init( int wait_time )

인수

wait_time poll 대기 시간 설정, 단위[ms], 0이상의

반환

-

주의

-


  • 예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c의 일부분 입니다.

 if(ex_init( 30))
 {
        ex_print_error("초기화 에러 발생 !!!아~슬프다.\n");
        exit(0);
 }

                                                                                                                                                                     

3.3. ex_add_fd () 파일 디스크립터 등록

  •  설명
    fd를 관리대상에 포함시키고, fd를 포함하는 ex_mng_t 구조체를 반환한다.

헤더

ex.h

형태

ex_mng_t *    ex_add_fd( int fd )

인수

fd 등록한 파일지시자

반환

NULL이면 실패, ex_mng_t 구조체 주소

주의

함수호출 ex_adjust_poll함수 호출이 필요.

 

  •  예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c의 일부분 입니다.

int fd[2];
int main( int argc, char **argv )
{
    ex_mng_t *pipe_in_obj;
    if (pipe(fd) < 0)
    {
        printf("pipe error\n");
        exit(0);
    }
   
    if(ex_init( 500))
    {
        ex_print_error("\n");
        exit(0);
    }
    pipe_in_obj = ex_add_fd(fd[0]);
    if(pipe_in_obj == NULL)
    {
        ex_print_error("\n");
    }
    ex_adjust_poll();
}

                                                                                                                                                                      

3.4. ex_mng_t  이벤트 매니져 구조체


typedef struct
{
    int       fd;      // 파일 지시자
    void   *priv;
   
    int (*on_read   )(void *   self);    // 이벤트 발생시 데이터를 읽어와 처리할 함수
    int (*on_write  )(void *   self);    // 이벤트를 발생 시키기 위한 쓰기 함수
} ex_mng_t;

  • 예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c의 일부분 입니다.

int fd[2];

int pipe_read(void * self)
{
    ex_mng_t *mng;
    char   buff[1024]={0,};
    int   read_size;
   
    mng = (ex_mng_t *)self;
   
    read_size = read( mng->fd, buff, sizeof(buff) );
   
    printf("pipe_read size :%d\n",read_size);

}

int main( int argc, char **argv )
{
    ex_mng_t *pipe_in_obj;
    if (pipe(fd) < 0)
    {
        printf("pipe error\n");
        exit(0);
    }
   
    if(ex_init( 500))
    {
        ex_print_error("\n");
        exit(0);
    }
    pipe_in_obj = ex_add_fd(fd[0]);
    if(pipe_in_obj == NULL)
    {
        ex_print_error("\n");
    }
    pipe_in_obj->on_read = pipe_read;                  // read 함수 등록
   
    ex_adjust_poll();
}

ex_add_fd() 를 통해 파일 디스크립터를 등록하고, 이벤트 발생시 호출할 함수 pipe_read ()을 등록하였다. 

                                                                                                                                                                     

3.5. ex_del_fd () 파일 디스크립터 등록

  •  설명
    fd를 관리대상에 삭제 시킨다.

헤더

ex.h

형태

void         ex_del_fd(int fd)

인수

fd 삭제할 파일지시자

반환

-

주의

함수호출 ex_adjust_poll함수 호출이 필요.


  • 예제
“3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c의 일부분 입니다.

int my_timeout(void)
{
 printf("My time out\n");
 ex_del_fd(fd[0]);     // 전송하는쪽 fd를 제거한다.

 ex_adjust_poll();      //poll을 재조정한다.
 return 0;
}

                                                                                                                                                                    
3.6. ex_adjust_poll () 관리자 최적화 기능 설정 

  • 설명
    poll 처리가 가능하도록 최적화 하게 플레그를 세운다.

헤더

ex.h

형태

int    ex_adjust_poll ( void )

인수

-

반환

0

주의

ex_loop함수호출 하기전에 필요하다.

  • 예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c를 참조하세요.

                                                                                                                                                                     

3.7. ex_loop () 이벤트 관리자 

  • 설명
    1. ex_adjust_poll_req 가 설정 되어 있으면, poll 처리가 가능하도록 최적화 한다.
    2. poll() 을 호출하여 event발생 여부를 확인한다.
    3. 이벤트가 발생하면 등록한 read , write함수를 호출한다.


헤더

ex.h

형태

int       ex_loop ( void )

인수

-

반환

0이면 성공, -1이면 실패

주의

-

  •  예제
    “3.8 sample.c  샘플 코드 참조“, 아래 예제는 sample_main.c를 참조하세요.

                                                                                                                                                                    
3.8. Sample_main.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include "ex.h"

#define TRACE printf("\rTRACE %s:%d \n",__FILE__,__LINE__);


//--------------------------------------------------------------
// 전역변수 선언
//--------------------------------------------------------------

int fd[2];

//--------------------------------------------------------------
// 설명 : 반대쪽 파이브에 넣은 값을 읽어온다.
//--------------------------------------------------------------

int pipe_read(void * self)
{
    ex_mng_t    *mng;
    char         buff[1024]={0,};
    int         read_size;

    mng = (ex_mng_t *)self;

    read_size = read( mng->fd, buff, sizeof(buff) );

    printf("[rx]pipe_read :%s , size:%d\n\n",buff ,read_size);

}

//--------------------------------------------------------------
// 설명 :후킹 test 함수
//--------------------------------------------------------------

int my_hooking_loop(int poll_state)
{
    //printf("My hooking_loop\n");
    write(fd[1],"abc",3);
    return 0;
}

//--------------------------------------------------------------
// 설명 :time out test 함수
//      :ex_init()시 설정한 EX_WAIT_TIME_DEFAULT 시간 이상 이벤트가
//       발생하지 않으면 호출되는 함수
//       test를 위해 timeout시 데이터를 전송하게 만듦
//--------------------------------------------------------------

int my_timeout(void)
{       
    //ex_del_fd(fd[0]);                         // 전송하는쪽 fd를 제거한다.
    //ex_adjust_poll();                         //poll을 재조정한다.   
    write(fd[1],"hello!.exlib^^",14);   
   
    printf("[tx]pipe_write :hello..exlib My time out \n");
    return 0;
}

//--------------------------------------------------------------
// 설명 : exlib를 이용하여 pipe간 데이터 전송을 처리하는 기능 구현
//--------------------------------------------------------------

int main( int argc, char **argv )
{   
    ex_mng_t *pipe_in_obj;
    if (pipe(fd) < 0)
    {
        printf("pipe error\n");
        exit(0);
    }

    if(ex_init( EX_WAIT_TIME_DEFAULT ))           // 기본 20msec
    {
        ex_print_error("\n");
        exit(0);
    }

    //ex_on_hooking_loop = my_hooking_loop;     // 요걸 등록하면 후킹된다.주의!!!
    ex_on_poll_timeout = my_timeout;                  // 요걸 등록하면 타임아웃시 등록된 함수가 호출된다.

    pipe_in_obj = ex_add_fd(fd[0]);                     // read에 사용될 fd를 exlib에 등록한다.
    if(pipe_in_obj == NULL)
    {
        ex_print_error("\n");
    }
    pipe_in_obj->on_read = pipe_read;                 // 이벤트 발생시 호출되는 함수 등록

    ex_adjust_poll();                                           // fd를 등록할 경우 반드시 해주어야한다.

    //write(fd[1],"abc",3);

    while( 1 )
    {
        if(ex_loop())                                           // 이벤트 발생시 위에서 등록한 pipe_read함수 호출한다.
        {
             ex_print_error("\n");
             exit(0);
        }
    }
    return 0;
}
                                                                                                                                                                    
4. 마치며
이상으로 exlib를 사용하기 위한 함수 설명과 이해를 돕기 위한 샘플 코드 설명 하였습니다.
추후에 exlib를 이용한 다양한 샘플 코드를 추가하여 널리 개발자는 복되게 하는 라이브러리는 개발하도록 노력하겠습니다.
exLib는 www.fsp21.org의 멤버들의 공동 작업으로  개발한 라이브러리라는 것을 다시 한번 말씀드립니다.

후속타로 나오는 ixLib는 정말 재미 있는 라이브러리 입니다.
입력 디바이스 드라이버로 받은 마우스, 터치스크린, 키보드 등의 데이터 정보를 ixLib를 이용하면
간단히 몇개의 함수를 이용하여 ,장치 입력을 그냥 날로 먹을 수 있게 해주는 아주 행복한 Lib가 될거 같습니다.

exLib로 약간 심심함을 느끼시는 분들은 조그만 기다려 주세요. 막강 조합
exLib + ixLib + gxLib 로 프로그램을 날로 먹게 해주는 Library가 만들어 집니다.

이상은 2009년 2월 8일 일요일 하루 문서작성으로 하루를 보낸 문경원 이였습니다.

감사합니다.
emoticon