고급 I/O 모델 : select() 시스템 호출

System Program/I/O 2014. 3. 1. 15:47

1. select() 시스템 호출

 

I/O 멀티플렉싱을 구현한 시스템 함수 중에 하나로 I/O Operation이 가능한 파일 디스크립터를 감시할 수 있다.

 

#include <sys/time.h>

#include <sys/select.h>

 

 int select(int nfds, fd_set *readfds, fd_set *writefds,

  fd_set *exceptfds, struct timeval *timeout);

 

준비된 파일 디스크립터 수를 리턴한다.

타임 아웃일 경우 '0'을, 에러가 발생하면 '-1'을 리턴한다. 

 

  • timeout 필드 설정에 따른 동작성

 

 timeout

설명 

 0

 select()함수는 블록되지 않고 지정된 파일 대기 상태인지만 확인하고 즉시 리턴한다.

 NULL

 읽기/쓰기/예외에 지정한 파일 디스크립터 중에 하나 이상 준비된 상태일 때 리턴

 '0' 이 아닌 값

 지정된 시간만큼 기다린다

 

  • 리턴값 상세

 

 리턴값

설명 

 -1

 에러가 발생한 경우이고, EBADF와 EINTR 에러로 에러가 설정될 수 있다.

 EBADF는 세개의 파일 디스크립터 집합에 유효하지 않는 파일 디스크립터가 설정된 경우

 EINTR은 시그널 핸들러에 의해서 발생한 것으로 EINTR은 자동으로 재시작되지 않는다.  

 0

 파일 디스크립터가 준비상태가 되기 전에 타임아웃된 경우

 양수

 한개 이상의 파일 디스크립터가 준비된 경우 

   

2. fd_set 데이터형 처리 함수들

 

위의 select() 함수 정의 부분에서 각각 읽기, 쓰기, 예외 파일 디스크립터 집합에 대한 기본 자료형

fd_set에 대한 자료형을 처리하기 위한 함수를 소개한다.

 

#include <sys/select.h>

void FD_ZERO(fd_set *fdset);

void FD_SET(int fd, fd_set *fdset);

void FD_CLR(int fd, fd_set *fdset);

 

int FD_ISSET(int fd, fd_set *fdset);

fd 가 fdset에 포함되어 있으면 '1'을 아니면 '0'을 리턴한다.  

 

위의 함수들에 대한 자세한 설명을 스킵한다. 이름에서 그냥 유추할 수 있다.

 

파일 디스크립터 집합의 최대 크기는 FD_SETSIZE 상수에 정의되어 있다. 리눅스에서는 1024이다.

 

3. 예제

 

temp.txt 파일을 읽기 전용으로 하나 열고, 여기에 데이터가 쓰여지면 select() 함수의 블록이

풀리고 표준출력에 파일에 입력된 내용을 출력한다. 간단한 예제를 통해서 함수 사용법을 익히는데 중점을 둔다.

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/types.h>
#include <sys/select.h>

#define MAX_BUFFER_LEN 256

int main(int argc, char *argv[])
{
	int retval, n;
	int fd;
	fd_set readfds, writefd;
	char buffer[MAX_BUFFER_LEN];
	
	if((fd = open("./temp.txt", O_RDONLY)) == -1)
	{
		perror("open : ");
		exit(EXIT_FAILURE);
	}

/*	
	newfd = dup(STDOUT_FILENO);
	if(newfd == -1)
	{
		perror("dup : ");
		exit(EXIT_FAILURE);	
	}
	
	close(STDOUT_FILENO);
*/	
	while(1)
	{
		FD_ZERO(&readfds);
		FD_ZERO(&writefd);
		FD_SET(fd, &readfds);
		
		retval = select(fd + 1, &readfds, &writefd, NULL, NULL);

		switch(retval)
		{
			case -1:
				perror("slect : ");
				exit(EXIT_FAILURE);
			
			default :
				if(FD_ISSET(fd, &readfds))
				{
					while((n = read(fd, buffer, MAX_BUFFER_LEN)) > 0)
					{
						printf("%s", buffer);
					}
				}
				
				memset(buffer, 0, MAX_BUFFER_LEN);
				break;
		}
		
		usleep(1000);
	}
	
	close(fd);
	exit(EXIT_SUCCESS);
}

 

'System Program > I/O' 카테고리의 다른 글

고급 I/O 모델 : epoll() 함수  (0) 2014.03.13
고급 I/O 모델 : poll() 함수  (0) 2014.03.12
access() 함수  (0) 2014.02.26
stat() 관련 함수  (0) 2014.02.26
fcntl() 함수  (0) 2014.02.21
: