점점 까먹어진다. 틈틈히 복습하자..



1. select function 좋은 예제


5초동안 표준입력으로부터 입력값을 받는다. 5초 이내로 글자를 받으면 (해당 fd에 대한 값이 변경) 입력받은 문자를 그대로 출력

 

소스
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define TIMEOUT 5
#define BUF_LEN 1024

int main(void) {

 struct timeval tv;
 fd_set readfds;
 int ret;

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

 tv.tv_sec = TIMEOUT;
 tv.tv_usec = 0;

 //  nfds is the highest-numbered file descriptor in any of the three sets, plus 1.

 ret = select (STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
 if (ret == -1) {
  perror("select");
  return 1;
 } else if (!ret) {
  printf ("%d senconds elapsed. \n", TIMEOUT);
  return 0;
 }

 if (FD_ISSET(STDIN_FILENO, &readfds)) {
  char buf[BUF_LEN + 1];
  int len;

  len = read(STDIN_FILENO, buf, BUF_LEN);
  if (len == -1) {
   perror("read");
   return 1;
  }

  if (len) {
   buf[len] = '\0';
   printf("read : %s \n", buf);
  }

  return 0;
 } 

 fprintf(stderr, "This should not happen!\n");
 return 1;

}

 

$ gcc select-demo.c
$ ./a.out
5 senconds elapsed.
$ ./a.out
123
read : 123
 


2. man select 내용

       /* According to POSIX.1-2001 */
       #include <sys/select.h>

       /* According to earlier standards */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);


       #include <sys/select.h>

       int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, const struct timespec *timeout,
                   const sigset_t *sigmask);

 

pselect 라는 것이 있는데. 차이점이 있다.
1. 시간과 관련된 struct이 다르다. select : timeval, pselect : timespec (초와 나노초)
2. 시그널 관련 sigset_t가 있다. 시그널과 관련된 mask를 파라미터로 사용한다. select 함수는 signal 파라미터를 사용하지 않는다.
   (pselect를 사용하는 예제를 거의 못본 것 같다. 나는 아직까지는 select만 사용하는 어플만 본 것 같다.)


pselect 예제는 sigprocmask 함수를 사용한 예제와 비슷하다.
 ready = pselect(nfds, &readfds, &writefds, &exceptfds,
                           timeout, &sigmask);


           sigset_t origmask;
           sigprocmask(SIG_SETMASK, &sigmask, &origmask);
           ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
           sigprocmask(SIG_SETMASK, &origmask, NULL);

 


3. poll 좋은 예제

#include <stdio.h>
#include <unistd.h>
#include <sys/poll.h>

#define TIMEOUT 5

int main(void) {
 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 * 1000);
 if (ret == -1) {
  perror("poll");
  return -1;
 }
 
 if (!ret) {
  printf("%d seconds elapsed. \n", TIMEOUT);
  return 0;
 }

 if (fds[0].revents & POLLIN) {
  printf ("stdin is readable.\n");
 }

 if (fds[1].revents & POLLOUT) {
  printf ("stdout is writable.\n");
 }

 return 0;
}

 

결과
$ gcc poll-demo.c
$ ./a.out
stdout is writable.

$ touch xx.txt
$ ./a.out  < xx.txt
stdin is readable.
stdout is writable.


4. man poll

       #include <poll.h>

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

       #define _GNU_SOURCE
       #include <poll.h>

       int ppoll(struct pollfd *fds, nfds_t nfds,
               const struct timespec *timeout, const sigset_t *sigmask);


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

 

5. select 와 poll 비교

- poll 은 가장 높은 fd에 +1을 할 필요가 없다.
- poll은 fd가 클 경우 좋다. select는 모든 fd의 비트를 검사한다. (select는 for loop에서 set 된 정보를 찾음)
  -> 그렇다고 select가 안좋다고 말할 수 없다. 이벤트가 자주발생하고 연속적인 시스템에서는 select를 사용 (apache http)
     poll은 어느 정도 분산되어 있거나 크기 제한이 없는 여러개의 array 형태로 넘겨서 사용할 때 유용하다.
            그리고, 필요한 것만 비교할 경우가 효과적이다.
- select는 fd set을 초기화를 해야 하지만, poll은 입력과 결과를 분리할 수 있다.
- select는 사이즈 제한이 있다.
- select가 이식성이 좋음. 어떤 시스템은 poll을 쓰지 않기도 함
- select의 timeout이 poll의 timeout보다 안정적임

 


6. 레벨트리거와 엣지트리거

select와 poll 은 레벨트리거

레벨 트리거  : 파일에 데이터가 있는지 여부에 대한 판단, 완전히 다 읽을때까지 계속 이벤트를 발생한다. 즉 '동안'에 집중
에지 트러거  : 파일이 특정 데이터를 저장하는 '특정시점'에만 발생

좋은 설명은 다음 블로그에서 잘 해놨다.
http://no1rogue.blog.me/30091246644
- 에지 트리거 : 인터럽트가 발생하여 레벨이 상승하거나 하강할 때.
- 레벨 트리거 : 인터럽트가 발생하여 그 레벨이 인가될 때.

 

 


출처
- http://no1rogue.blog.me/30091246644
- 리눅스 시스템 프로그래밍, 한빛미디어
- http://kldp.org/node/35279

Posted by 김용환 '김용환'

댓글을 달아 주세요