select를 활용한 event check, FD_SET, FD_ISSET
select() 를 이용하여 non-block I/O 처리를 만들어보겠다.
크게 아래의 과정을 거쳐서 동작한다.
1. FD_SET 을 통한 descriptor 셋팅
2. FD_SET된 FD_LIST들을 select() 를 통해 event 검사
3. timeout 시 동작할 행위
4. timeout 전 event 발생 시 FD_ISSET 처리
소스코드 내에 주석을 달아뒀으니 참고하여 활용하자.
소스코드
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <fcntl.h>
int main(int _argc, char *_argv[]) {
int rc;
struct timeval t_timeout;
// device의 open이 되었다고 가정하고 진행한다.
int dev_fd = 3;
int max_fd = dev_fd + 1;
fd_set fd_reads;
while( 1 ) {
FD_ZERO(&fd_reads);
FD_SET(dev_fd, &fd_reads);
// timeout: 최대 1초까지 event 대기
t_timeout.tv_sec = 1; // sec
t_timeout.tv_usec = 0; // msec
// fd_reads에 FD_SET 된 descriptor들을 최대 t_timeout에 설정된 시간만큼 기다린다.
if( (rc = select(max_fd, &fd_reads, NULL, NULL, &t_timeout)) < 0 ) {
printf("execute() select failed : [%02d] %s\n", errno, strerror(errno));
continue;
// t_timeout에 설정된 시간까지 event가 없다면 timeout 처리된다.
} else if( rc == 0 ) {
printf("select() timeout, continue loop..\n");
continue;
}
// timeout 전에 event가 발생했다.
// FD_ISSET 을 이용하여 fd_reads 중 어느 descriptor에서 event가 발생했는지 확인한다.
if( FD_ISSET(dev_fd, &fd_reads) ) {
printf("select() event [dev_fd]\n");
}
}
return 0;
}
이번 예제에서는 1개의 descriptor 만 사용했지만 복수개(e.g. socket client..)의 descriptor의 event를 감시해야 할 때는 배열을 생성하여 배열에 descriptor들을 넣어주고 FD_SET을 통해 fd_reads에 set을 하자.
그리고 event 발생 시 FD_ISSET을 배열에 저장된 descriptor의 갯수만큼 반복하여 체크하면 된다.
끝.
'IT > programming' 카테고리의 다른 글
Rest API 요청 언어별 정리, CURL/PHP/PYTHON/C/C++/QT/JAVA/Node.js (6) | 2022.01.17 |
---|---|
[C/C++] C언어 MAC 주소 읽기 구현, get mac address (0) | 2022.01.16 |
[C/C++] 전역 네임스페이스, 시스템 함수와 동일한 클래스 메서드 이름 사용 방법 (0) | 2022.01.14 |
[C/C++] C++ curl handler class 예제, C언어 curl 구현 (10) | 2022.01.13 |
[C/C++] C언어 Big-endian <-> Little-endian 상호 변환 (0) | 2022.01.13 |
댓글