LinuxProgramming

[Linux] select()

mintuchel 2023. 11. 22. 00:05

서버일 경우에는 불필요하게 계속 read를 할 필요가 없음

그래서 데이터가 없는 경우에는 blocking 해주는게 맞음

 

서버는 만약 아무도 안보내면 blocking 하길 원함

만약 누가 보내면 그때 blocking을 해제하고 읽을 수 있었으면 함

그리고 만약 1명 이상이 보내면 순서대로 읽었으면 함.

이런 프로그램을 만들려면 select를 사용해야함.

 

참고로 select는 read가 아님

어느 파이프가 준비되었는지 알려주는거지 read까지 해주는게 절대아님

 

여러 파이프 중에서 어느 파이프에서 데이터가 왔는지를 검사하는 시스템 콜임.

그래서 검사를 해서 한 군데에서라도 데이터가 안왔으면 select에서 block을 함.

read에서 blocking을 하는게 아니라 select에서 blocking을 함.

 

한 군데에서라도 온다? 그럼 어느 파이프가 읽기쓰기 가능한지 표시해줌(fd_set에)

그래서 그걸 확인하고(FD_ISSET으로) 해당 파이프들을 read write하면 됨.

 

만약 다 안보낼때는? select에서 영원히 blocking됨.

 

이런 영원한 blocking을 막기 위한 timer 기능도 있음.

일정한 기간동안 데이터가 없으면 timeout해주는 기능임.

timeval을 사용해서 select의 마지막 인자로 &tv를 넣어주면 됨.

 


 

다수의 pipe를 쓸때 사용하는 system call 이다

다수의 pipe를 다룰때 현재 어떤 pipe들이 준비되었는지를 확인할 수 있다

 

select 함수를 사용하면 한 묶음으로 모아둔 여러개의 file descriptor들을 동시에 관찰할 수 있다

 

이때 이 fd들을 한 묶음으로 묶어서 select 함수로 넘겨줄때 쓰는데 fd_set 이다.

fd_set은 말그대로 fd들의 집합인데 bit 배열로 표현된다.

 

 

따라서 이 fd_set을 인자로 넘겨주어야하므로 fd_set 함수들을 통해 원하는 file descriptor들을 fd_set에 넣어줘야함.


[file descriptor set functions]

 

c++ bitset 사용한다고 생각하면 쉽다.

무조건 0 아님 1이다. 내가 조사하고 싶거나 하기 싫거나


[select()]

select(p[2][0]+1, &set, NULL, NULL, &tv)

1. int fds : 조사할 file descriptor 개수 (p[3][0]+1 이런식으로 표현)

표준 입출력 포함 입력 확인을 하려는 pipe 번호의 범위

2. fd_set 3 종류

조사하고 싶은 읽기 파이프 집합([0]번들) 조사하고 싶은 쓰기 파이프 집합([1]번들)

3. timeval

timeout 설정


[select 의 return 값]

 

select return 값이 0보다 크면 읽거나 쓸 파이프가 존재한다는 얘기다

0보다 작으면 일정 시간안에(timeval) 변화가 일어난 파이프들이 없다는 얘기다.

 

select는 됐다고 떴는데(FD_ISSET)의 결과, read의 return값이 0일 수 있음.

 

데이터가 있다고 해서 읽었는데 read의 return값이 0인 경우가 있나? ㅇㅇ 있음.

read return == 0 : 클라이언트가 종료되면 파이프가 닫힘.

즉 클라이언트가 종료됐는데 이걸 서버가 클라이언트가 종료된지 모르고 계속 읽어서 0이 계속 오는거임.

 

0이 return되는 것은 0은 읽을 수 있는 상태라고 파악한다는 거임.

따라서 데이터가 왔다고 판단함.

 

그래서 클라이언트 pipe가 닫혔는지 아닌지를 read return == 0으로 판단하면 됨.

그리고 해당 파이프를 FD_CLR로 fd_set 에서 지워주면 된다.

 


 

 

1. select 함수를 돌면서 인자로 집어넣은 fd_set이 bit 연산 대상이 되면서 바뀐다

따라서 set = master 로 복사해서 사용하는 것이다.

 

2. timeval 도 while문을 돌면서 여러번의 select 함수에 사용되면서 값이 바뀐다.

따라서 매 조사 이후에 초기화 시켜줘야한다.

이건 while 문 맨 앞에서 해도 되고 맨 뒤에서 해도 됨

 

3. 만약 timeout이 되었으면 조사할 bit를 0으로 만들어주면 된다.

그래서 FD_CLR를 해주는 것이다.