티스토리 뷰

select 시스템콜이 0보다 큰 값을 리턴하면 , 0이면 타임아웃, -1이면 에러이다.


Select가 양의 정수를 리턴하는 상황

select시스템콜은 정상리턴할때 read보따리 write보따리 등에 들어있는 소켓이 I/O가

 가능한 상태가 되면 그 가능해진 소켓의 숫자를 리턴한다.


Select가 0을 리턴하는 상황

select의 마지막 인자로 넣은 시간동안 소켓보따리의 소켓이 I/O준비가 됬는지 검사하다가 타임아웃 되는 순간 0을 리턴시킨다.

마이크로 세컨드는 10의-6승인데 실제로는 마이크로 세컨드 기준으로 시간을 조절하기는 힘들다.


select가 -1를 리턴하는 상황

select에서 블락되어있는 상태에서 시그널 핸들러가 호출되면 그 블락 시스템콜이 이상한값을 리턴할 가능성이 있으므로

앞에서 그 블락 시스템콜을 -1리턴 시켜버리고 errno에 EINTR(Error Inturrept)를 리턴시킨다고 했었다. 

바로 이런 경우에 select가 -1을 리턴시킨다.


Select의 timeval조절

timeval 인자에 NULL을 넣으면 i/o준비가 된 것이 있을때까지 무한정 기다리겠다는 의미.

timeval에 0을 넣으면 블락 되지 않고 소켓보따리에 i/o준비가 된 소켓이 없으면 바로 0을 리턴 시킨다.


위의 두 사진은 select를 위한 준비과정이라고 볼 수 있다.

위에서 계속 소켓보따리라는 표현을 했는데 사실 select 시스템 콜은 소켓에 대해서만 i/o검사를 하지 않는다.

stdin(키보드입력)이나 파일입력 소켓입력등 입력에 대한 검사를 할때 read전용 보따리에 그 검사할 파일들을 넣는다.

앞으로는 소켓 보따리라는 표현 대신 그냥 read용 보따리또는 파일 보따리라는 표현을 하겠다.

(리눅스에서는 모든것들을 파일로 지칭한다. 키보드,모니터,소켓등 모두 파일로 취급한다)


보따리에 파일을 넣는 역할을 하는 함수가 FD_SET이다. 1번 파일디스크립터를 가지는 파일을 

rset이라는 read용 보따리에 넣어서 만약 그 파일이 입력할 준비가 되있으면 select가 리턴 되게끔 하는것이다.


FD_ZERO는 파일 보따리를 0으로 초기화 하는 역할. FD_CLR는 파일 보따리에서 그 파일을 뺌으로써 

그 파일에 대해 더이상 i/o가 준비 됬는지 안됬는지를 검사하지 않겠다는 의미이다.


FD_ISSET은 그 파일 보따리에 있는 파일때문에 select가 블락에서 깨어났냐 라는 의미이다.

다시말해서, 그 파일이 읽을 준비가 되었는지를 확인하기 위한 함수이다.

보따리 안에 파일들이 여러개 있는데 이 파일들을 하나하나 살피면서 읽을 준비가 됬는지 안됬는지

확인하는 과정이 FD_ISSET이다. 또한 select시스템콜은 파일 보따리에서 입출력이 준비된 파일을 꺼내 사용하겠다는 의미이다.


파일 보따리에 입출력이 준비된 파일이 하나도 없으면 있을때 까지 기다린다.(timeval을 NULL로 세팅한경우)

파일 보따리에 입출력이 준비된 파일이 없으면 바로 파일 보따리를 닫고 확인과정을 멈춘다(timeval을 0으로 세팅한경우)



RST가 서버로 부터 오는 경우 : 서버 자식 프로세스가 종료됬는데 클라이언트에서 데이터를 보냈을때 errno = ECONNRESET,-1리턴

FIN이오는 경우 : 서버 자식 프로세스가 종료 되었을때


우리는 read 블락 될수 있는 파일을 클라이언트에서 2개를 사용했다.(stdin,socket)

이 2개의 파일이 순서대로 read되어야 정상 작동 되게끔 프로그래밍 해서 문제가 발생했었고 그걸 막기 위해 아래와 같이

select시스템콜을 사용하는 프로그램으로 코드를 바꿔준다.


maxfdp1 -> max file descriptor + 1 -> 파일디스크립터 55번이 그 프로세스에서 사용하는 select를 호출하기 전에 가장큰 fd번호라고 하자.

가장 작은 fd는 0이다. stdin(0) stdout(1) stderr(2) 이기 때문에 프로그램으로 만든 fd는 3부터 시작하게 된다.

select의 첫번째 인자로 들어가는 정수값은 몇개의 소켓을 검사하겠냐는것이다.

만약에 소켓이 2개있다고 했을때 첫번째 소켓은 3번 두번째 소켓은 4번 fd를 할당 받을것이다.

그런데 사실 4번 fd라는것은 그 프로세스가 사용하는 5번째 파일이라는 의미이다.

(0번,1번,2번,3번,4번)


그렇기 때문에 fd의 max에 1을 더해서 첫번째 인자에 넣어야한다.(5개의 파일을 검사하겠다는 의미)

만약에 +1을해주지 않고 그냥 fd 4를 첫번째 인자로 넣게 되면 마지막 파일인 4번fd를 갖는 소켓은 select에 의해서 검사되지 않을 것이다.


마지막 인자가 NULL이므로 블락에서 i/o준비가 될때까지 무한히 기다려라라는 의미이다.


FD_ISSET은 false 또는 true를 리턴하는 매크로이다.



바쁜 웹 서버의 경우에 유저 프로세스에서 필요로하는 데이터가 한번에 오는것이 아니라 Flow control등의 이유로

찔끔찔끔 수신 되는 일이 생길수 있다. 이런 경우에 서버의 응용 프로그램이 100byte를 모두 수신해야만 의미가 있는 프로그램인경우

20byte씩 5개를 모두 받아야 한다. 99byte를 받은것만으로는 의미가 없는 프로그램일 경우가 많이 생길수 있다.


그래서 소켓에 옵션으로 watermark를 두어서 100byte가 커널에 도착한 경우에만 read하게끔 할 수 있다.

watermark는 수표라고 불리는데, 물의 수위를 나타낸다. 그 기준점을 넘는 경우에만 어떤 일을 처리하게끔 하는 지표이다.


만약에 소켓 옵션으로 watermark를 두지 않으면 1byte가 커널에 도착할때마다 프로세스가 깼다가 다시 블락됬다가 하는일이 반복 되므로

오버헤드가 커지게 된다. 그렇기 때문에 이런 경우에 소켓 옵션을 꼭 주는것이 좋다.












댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함