select() 함수에 대해서 질문이 있습니다.

sevp2027의 이미지

로버트 러브 가 쓴 "리눅스 시스템 프로그래밍"이라는 책을 보고 있습니다.

여기서 select() 에 대한 설명을 보면

select() 호출은 파일 기술자가 입출력을 수행할 준비가 되거나 옵션으로 정해진 시간이 경과할때까지 차단한다

라고 되어있습니다.

그리고 이 설명에 대한 예제로 다음과 같은 코드가 나와 있습니다.

#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;
 
	ret = select(STDIN_FILENO +1, &readfds, NULL, NULL, &tv);
 
 
 
	if(ret ==-1)
	{
		perror("select");
		return 1;
	}
	else if(!ret)
	{
		printf("%d seconds elapsed. %d  \n",TIMEOUT, ret);
		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("%d         read : %s\n",ret,buf);
		}
 
		return 0;
	}
	fprintf(stderr, "this should not be happend! \n");
	return 1;

제가 이해하기론 select() 함수는 readfds, writefds, exceptfds에 등록된 fd들에 대해서 모니터링을 하면서
readfds 의 경우 어떠한 입력이 들어오고 그리고 그 입력을 다 받아서 다시 입력을 받아들일수 있는 순간이 되거나
혹은 timeout이 지나는 동안까지

process를 while문과 같이 차단한다는것 같은데 제가 옳게 이해 한건가요?
차단 이라는 말을 정확하게 이해를 못하겠습니다 일부에서는 블락으로 표시도 하던데 실행을 시켜보면 실제로 timeout 기간동안 컴퓨터가 아무 반응을 하지 않습니다.
이 기간동안 이렇게 있는 상태를 차단 이라고 표현 한걸까요?

그렇다면 제가 위에서 굵은 글씨로 적은 것 처럼 이 예제에서는 STDIN_FILENO에 키보드로 부터 입력이 들어오고 이것이 모두 마쳤으므로 이제 다시 입력을 받을수 있는 상황 즉 입출력을 수행할 준비가 될때까지 컴퓨터가 멈추어 있는것도 제가 옳게 이해를 한건가요?

지식이 얄팍하다 보니 질문도 엉성한것 같습니다.
예제만으로 이해를 못하는 초보를 도와주세요.

감사합니다.

drinkme의 이미지

'차단'이라는 말을 block 일 겁니다.
해당 process가 sleep에 들어가는 거겠죠.

위의 예제에서 stdin에 뭔가 들어올때까지 (원가 입력될때까지),
혹시 해당 시간동안 해당 process가 block (멈추는 것처럼 보인다고 보시면 됩니다.) 됩니다.

rgbi3307의 이미지

TIMEOUT 시간동안 sleep 하고 있다가 STDIN_FILENO로 부터 입력신호가 발생하면 깨어나서
if(FD_ISSET(STDIN_FILENO, &readfds))
{ 문장처리 } 됩니다.

입력신호 발생없이 TIMEOUT이 경과되면, select는 널을 리턴하여
else if(!ret)
{ 시간초과 메세지 출력 }

질문에 대한 답변을 요약하면,
select() 함수는 TIMEOUT 시간동안 사건이 발생할때 까지 sleep 합니다.

From:
*알지비 (메일: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

sevp2027의 이미지

제가 이해가 느려서 몇가지만 더 여쭈어보겠습니다. 미리 감사드립니다.
FD_SET을 통해 STDIN_FILENO를 readfds에 포함시켰습니다.
그리고 FD_ISSET을통해서 입력신호가 들어올 경우 이 부분이 동작한다고 하셨습니다.
그렇다면 입력신호를 받아들이는 그 순간 STDIN_FILENO는 키보드로부터 입력을 받는데 문제가 없으므로 ISSET이 참으로 동작한다고 제가 생각을 해도 되는건가요?

혹시나 다른 프로세스에 의해 입력을 받는데 문제가 있거나 해서 문제가 생기면 ISSET에서 FALSE를 띄울수도 있는건가요?

이게 select()의 원래 목적인거 같기는 한데 예제에서는 단순히 fd하나에 대해서만 설명을 해주고 있어서..
동기식 다중 입출력 메커니즘이라는게 정확하게 이해가 안되고 있는것 같네요..ㅠ

rgbi3307의 이미지

위 프로그램을 실습해보시면,
"입력신호를 받아들이는 그 순간 STDIN_FILENO는 키보드로부터 입력을 받는데 문제가 없으므로 ISSET이 참으로 동작한다" 라고 언급하신 것이 맞다고 느낄실 겁니다.
5초동안 sleep(block) 대기하는 도중 입력장치(키보드)에서 입력신호가 들어오면 ISSET이 동작합니다.
(키보드 엔터키를 쳐야함)

그리고 multiplexed I/O에 대해서 언급하셨는데,
select()는 여러개의 장치가 fd에 설정되어도 입출력 가능한 하나의 장치만 동작하는 것으로 알고 있습니다.
즉, 장치번호 7번과 9번 이렇게 설정되어 있어도, 7번이 입력가능 하다면, 7번 하고만 소통하는거죠.
그래서 multiplexed I/O를 하실려면, select() 다음에 책에서 설명하고 있는 poll()를 사용하셔야 합니다.

From:
*알지비 (메일: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))

cinsk의 이미지

> select()는 여러개의 장치가 fd에 설정되어도 입출력 가능한 하나의 장치만 동작하는 것으로 알고 있습니다.

사실이 아닙니다.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

ymir의 이미지

대개는 block 을 봉쇄로 해석하던데, 그 책에서는 차단이라고 했나 보네요.
몇몇 함수들은 data 나 event 가 없으면, 바로 return 하지 않고 data 나 event 가 발생할 때까지 waiting 합니다.
그래서 다음 routine 으로 진행하지 않기 때문에, block 되었다고 표현합니다.
흔한 예로 blocking/non-blocking socket 을 들 수 있겠네요.
select 역시 주어진 fdset 에 event 가 발생할 때까지 waiting 하게 되는데..
만약 timeout 이 주어지면 해당 시간까지만 block 되고, 시간 초과시에는 0 을 return 하게 됩니다.

fdset 에 포함된 fd 에 event 가 발생하면 select 는 즉시 return 하는데..
어느 fd 에서 event 가 발생했는지 확인하기 위해서 FD_ISSET 매크로를 이용합니다.

예를 들어, 하나의 server 에 여러개의 client 가 붙어있고..
여러개의 socket fd 를 readfds 에 넣어서 select 로 감시하고 있다면..
그 client 중에 아무나 data 를 보낸 경우, select 는 즉시 return 하겠지만..
어느 fd 에서 event 가 발생했는지는 알 수 없으므로..
각각의 fd 에 대해 FD_ISSET 으로 확인합니다.
만약 FD_ISSET 이 non-zero 라면, 해당 fd 에 data 가 있는게 확실시 되므로..
적절히 data 를 읽어들이면 됩니다.

위처럼 하나의 프로세스에서 여러개의 client 에 대한 동시 처리가 가능한 형태를..
I/O Multiplexing 이라고도 부릅니다.
물론 select 외에 poll 이나 epoll 등의 여러가지 방법으로 I/O Multiplexing 이 가능합니다.

아래의 sample code 를 보시면 도움이 될 것 같습니다.
http://www.developerweb.net/forum/showthread.php?t=2933

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

jick의 이미지

select() 호출은 파일 기술자가 입출력을 수행할 준비가 되거나 옵션으로 정해진 시간이 경과할때까지 멈춰서 기다린다

...라고 번역했으면 아무런 문제가 없었을 것을...

...가끔씩 보면, 하나의 영어 단어를 하나의 한국어 단어로 단순치환하면 사람이 이해할 수 있는 번역이 나온다고 믿는 사람들이 있는 것 같습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.