1. 개요

 

    이 문서는 루아에서 poll() 함수를 지원하기 위해서
    필요한 설계를 기술한다.
   
2. poll() 함수의 C 형식

 

    리눅스에 poll() 함수는 다음과 같은 특성을 갖는다.
   
    기능
   
        파일 디스크립터에서 설정한 이벤트가 발생하기를 기다린다

 

    형태

 

        #include <sys/poll.h>

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

 

    설명

 

        이 함수는 timeout이 지나기 전까지 struct pollfd의 배열에 등록된 이벤트를 대기한다.

 

    매개변수   
   
        - ufds      : 이벤트 배열의 선두 주소
        - nfds      : 이벤트 수
        - timeout   : 밀리 초 단위의 대기 한계 시간
 
    반환값
   
        성공하면 양수값이 반환되며, 반환된 숫자는 revents 필드의 구조체 숫자다

         (보고된 이벤트나 에러가 있는 파일 디스크립터).
        0은 호출에 타임아웃이 걸렸고, 어떤 파일 디스크립터도 선택되지 않았음을 가리킨다.
        에러가 발생하면 -1이 반환되며, errno는 다음 중 해당되는 값으로 설정된다.
   
        - ENOMEM    : 파일 디스크립터 테이블을 할당할 공간이 없다.
        - EFAULT    : 인자로 주어진 배열이 호출 프로그램의 주소 공간에 포함되지 않았다.
        - EINTR     : 요구된 이벤트 전에 신호가 발생했다

 

    이벤트 구조체

 

        이 함수를 사용하기 위한 이벤트 구조체는 다음과 같다.

 

            struct pollfd
            {
                 int fd;           // 파일 디스크립터
                 short events;     // 요구된 이벤트
                 short revents;    // 반환된 이벤트
            };


        - fd    : 필드는 열려진 파일 디스크립터를 포함한다
        - events    : poll 함수를 탈출하기 위한 이벤트 조건
        - revents   : poll 함수를 탈출했을 때 일어난 이벤트

        events와 revents는 비트 마스크 함수로, 다음 값들의 OR 조합이다.

            #define POLLIN      0x0001  // 읽을 데이터가 있다.
            #define POLLPRI     0x0002  // 긴급하게 읽을 데이터가 있다.
            #define POLLOUT     0x0004  // 지금 쓰기가 봉쇄되지 않았다.
            #define POLLERR     0x0008  // 에러 조건
            #define POLLHUP     0x0010  // Hung up
            #define POLLNVAL    0x0020  // 무효한 요구: fd가 열리지 않았다.

   
3. poll() 함수의 사용예

 

    poll() 함수는 다음과 같은 일반적인 사용법을 갖는다.
   
       #include <stdio.h>
      #include <string.h>
      #include <fcntl.h>
      #include <termios.h>
      #include <sys/time.h>
      #include <sys/types.h>
      #include <unistd.h>
      #include <sys/poll.h>
     
      int main(int argc, char **argv)
      {
          int    sfd1, sfd2, sfd3;
         
          struct pollfd Events[3];
          int    retval;
          char   buff[256];
          int    readcnt;
      
          sfd1 = open("/dev/ttyS1", O_RDWR | O_NOCTTY);
          sfd2 = open("/dev/ttyS2", O_RDWR | O_NOCTTY);
          sfd3 = open("/dev/ttyS3", O_RDWR | O_NOCTTY);
              :
          // 각각의 시리얼 환경 설정 루틴들
              :
         
          memset(Events, 0, sizeof(Events));
     
          Events[0].fd     =  sfd1;
          Events[0].events = POLLIN         // 수신 이벤트
                           | POLLERR;       // 에러 이벤트
     
          Events[1].fd     =  sfd2;
          Events[1].events = POLLIN         // 수신 이벤트
                           | POLLERR;       // 에러 이벤트
             
          Events[2].fd     =  sfd3;
          Events[2].events = POLLIN         // 수신 이벤트
                           | POLLERR;       // 에러 이벤트
         
          while(1)
          {
              // 사건이 생기기 전에 대기한다.
              retval = poll((struct pollfd *)&Events, 3, 5000); < 0)
              if(retval < 0)
              {
                  perror("poll error : ");
                  exit (EXIT_FAILURE);
              }
              if(retval == 0)
              {
                  printf("5초 안에 아무 데이터도 없었다.\n");
                  continue;
              }
             
              for (i = 0; i < 3; i++)
              {
                  // 에러에 대한 검사를 수행한다.
                  if(Events[i].revents & POLLERR)
                  {
                      printf("장치 에러 발생.\n");
                      exit (EXIT_FAILURE);
                  }   
     
                  // 수신된 데이터가 있는지를 검사한다.    
                  if(Events[i].revents & POLLIN)
                  {
                      readcnt = read(i, buff, 256);   
                      write(i, buff, readcnt);
                  }   
              }   
          }
         
          close(sfd1);
          close(sfd2);
          close(sfd3);
         
   
4. 루아에서 지원하도록 하려는 poll 모듈 함수들 및 특징

 

    루아에서는 다음과 같은 함수를 지원 하도록 작성될 예정이다.

 

    pollmodule.create(max);

 

        설명 : poll 모듈에서 poll 객체를 생성한다.

        매개 : 관리 가능한 최대 인벤트 수

        반환 : poll 객체

 

    poll.free();       

 

        설명 : 할당된 poll 객체를 해제 한다.

        매개 : 없음

        반환 : poll 객체

 

    poll.clear();      

 

        설명 : poll() 함수를 사용하기전 모든 상태 클리어
                    내부적인 초기화 처리

        매개 : 없음

        반환 : true  - 정상적인 처리가 됨
                    false - max 값이 너무 크다.
       
    poll.event( fd, poll_in, poll_pri, poll_out, poll_err, pollhup );      
   
        설명 : 대기할 이벤트 추가를 추가 한다.

        매개 : fd        - number   추가할 파일 디스크립터
                    poll_in   - boolean  읽을 데이터가 있다는 것을 감시          기본값 true
                    poll_pri  - boolean  긴급하게 읽을 데이터가 있다는 것을 감시 기본값 false
                    poll_out  - boolean  쓸수 있는 상태를 감시                   기본값 false
                    poll_err  - boolean  에러 상태를 감시                        기본값 false
                    poll_hup  - boolean Hung up 상태를 감시                      기본값 false
       
        반환 : true  - 정상적으로 등록되었다.
                    false - 지정된 max 값 이상으로 추가 하였다.

 

    poll.wait( time_over_msec );
   
        설명 : poll() 함수를 내부적으로 실행하여 대기 한다.

        매개 : time_over_msec - number 아무런 이벤트가 발생하지 않았을 때 이 함수를 탈출할 임계시간 (미리초 단위)

        반환 : true  - 시간 초과 또는 이벤트가 발생함
                    false - 치명적인 에러

    poll.is_timeout();

 

        설명 : 시간 초과가 발생했는가를 검사한다.

        매개 : 없음

        반환 : true  - 시간 초과 발생
                    false - 시간 초과 발생하지 않음
   
    poll.is_in( fd );

 

        설명 : 읽을 데이터가 있을때 발생하는 이벤트가 있는지를 검사 한다.

        매개 : fd        - number   검사할 파일 디스크립터

        반환 : true  - 이벤트 발생
                    false - 이벤트 없음
   
    poll.is_pri( fd );
   
        설명 : 긴급하게 읽을 데이터가 있을때 발생하는 이벤트가 있는지를 검사 한다.

        매개 : fd        - number   검사할 파일 디스크립터

        반환 : true  - 이벤트 발생
                    false - 이벤트 없음

 

    poll.is_out( fd );
   
        설명 : 써 넣을 수 있는 상태일때 발생하는  이벤트가 있는지를 검사 한다.

        매개 : fd        - number   검사할 파일 디스크립터

        반환 : true  - 이벤트 발생
                    false - 이벤트 없음

 

   poll.is_err( fd );

 

        설명 : 에러 상태일때 발생하는  이벤트가 있는지를 검사 한다.

        매개 : fd        - number   검사할 파일 디스크립터

        반환 : true  - 이벤트 발생
                     false - 이벤트 없음
   
    poll.is_hup( fd );
       
        설명 : Hung up 상태일때 발생하는  이벤트가 있는지를 검사 한다.

        매개 : fd        - number   검사할 파일 디스크립터

        반환 : true  - 이벤트 발생
                    false - 이벤트 없음
   
5. 루아에서 사용할 예

 

     poll_module = require "poll";

    poll = poll_module.create(3);

    while true do
   
        if poll.clear()  == false then break; end;
        if poll.event(fd) == false then break; end;
       
        if poll.wait( 3000 ) == false then break; end;
       
        if poll.is_timeout() then
       
           print( "poll time out\n" );
          
        else
       
            if poll.is_read( fd ) then

              print( "serial read event\n" );
              rxdata, rxsize = serial.read( com1 );       

            end;
       
        end;

    end;
   
    poll.free();
    poll_module = nil;

 

C000_lua.gif