i/o multiplexing & nonblocking socket, multi-thread 질문
socket i/o(select or poll) thread (io thread) - 1개
socket buff에서 데이타를 read 해서 data를 가공하는 thread(read thread) -1개
데이타를 가공하여 write하는 thread(work thread) - n개
로 서버를 구성하려 합니다.
이에 대한 질문입니다.
1.
프로그램을 짜다가 보니 socket i/o thread와 data를 read하는 thread는 따로 뗄 필요가 없다고 생각이 듭니다.
왜냐하면 socket i/o thread에서 socket에 event가 발생했을때
read thread에게 socket을 넘기고, read thread에서 read()를 먼저할지 socket i/o thread가 다시 event를 먼저 감지할지 우선순위가 보장되지 않기 때문입니다..
물론 mutex로 문제를 해결할 수는 있지만, 더 효율적인지 모르겠더군요..
제 생각이 맞습니까~?
2.
1번의 이유로 인해
socket i/o thread에서 data를 read한 후 work thread를 호출하는 구조로 바꿨습니다.
socket i/o thread와 work thread간에 동기화를 위한 자료구조는 어떻게 구성해야 합니까?
저의 경우는
mutex 1개, cond 1개로 socket i/o thread와 work thread간 동기화를 시켰는데요...
이렇게 구성했을경우에 여러 client가 접속해서 data를 계속 send() 했을경우 socket i/o thread에서 하나의 client에 대해서만 event 감지가 일어납니다.
usleep()으로 잠깐의 여유(?)를 주니까 올바른 동작을 하더군요.. 왜 이런겁니까~?
가르침을 주소서~ ^_^
1. [code:1]read event 감지 -> 감시 대상에서 제
1.
read event 감지 -> 감시 대상에서 제외 -> 소켓 전달 -> read 및 작업 (io thread는 event 감시 중)-> 소켓 되돌려주기 -> 감시 대상에 포함 -> read event 감지
순으로 하면 우선순위는 문제가 될 것 같지 않습니다만..
2. 코드가 없으면 어떤 문젠지 알기 힘들 것 같네요.
가르침은 아니구요.
우선 2번.
혹시 i/o thread에서 select, poll 을 하실때 타임아웃을 0으로 하고 무작정 루프를 돌리신겁니까?
usleep()으로 잠깐의 여유를 주셨다는걸 보면... 아마 select, poll을 가지고 이벤트를 대기하는게 아니라 체킹하는데 쓰신 듯 합니다만.
만약 그런거라면..
비선점형, 선점형을 떠나 어플리케이션의 쓰레드가 그렇게 쉴 새 없이 돌아갈 경우 커널의 작업이 방해받을 수 있습니다.
순위역전이 발생하여 수신된 패킷을 처리하고 이벤트를 만들어야 할 커널 대신 쉴 새 없이 돌아가는 응용프로그램이 자원을 더 오래 독점하기때문이죠.
할 일이 없을 때 반드시 쉬고, 할 일이 있는 시간만 일하도록 만드는게 가장 이상적인 방법입니다. 그리고 할 일이 꾸준히 있다 하더라도 타 프로세스/쓰레드와의 동시 실행관계를 살펴 적절히 yield를 하게 만들어야 합니다.
1번...
TCP 서버 개발에서 i/o demuxing은 단순히 수신 이벤트만 감지하기 위한건 아닙니다. reactor의 경우 송신 재개 가능 이벤트, proactor의 경우 송신 완료 이벤트를 감지하려는 목적도 있죠.
저같은 경우엔 보통
(이벤트 감지 - 전송 처리 - 모델 처리)
의 세가지 분류를 기본으로 설계합니다.
암튼 지금 돈 받고 일하시는게 아니라 개인적으로 공부하시는거라면...
여러가지 방식으로 시도를 해 보시는게 좋을 듯 합니다^_^;
말씀하신 그런 방식도 나쁘진 않겠네요..
가장 효율적인 방식은... 각 상황에 맞는 방식이죠. 그걸 알기 위해선 끊임없는 시도가 필요할테구요.
어떤 고정적인 틀을 잡고 이대로만 한다는 식으로 하면... 결국 STL처럼 본말이 전도되는 결과를 만들어내니까요.
님ㅎ 즐~
답변 감사드립니당.. ^^1[quote]read event
답변 감사드립니당.. ^^
1
kane님께서 말씀하신 방법 괜찮아 보입니다.
하지만 i/o thread와 read thread간에 fd_set을 위한 별도의 동기화 과정이 필요할듯 보입니다.
그리고, 테스트를 해보진 않았지만 효율적인 면에서는 떨어지지 않을까 생각이 드는데요..
select(..)의 예를 들면 감시대상에서 제외(FD_CLR(..)), 감시대상에포함(FD_SET(..)) 행위를 계속 해줘야 하니까요...
한번 테스트 해봐야 겠군요...^^
2.
timeout을 0으로 주지않았습니다.
맞습니다..
block이 아니라 nonblock 입니다. 체킹하는거죠...
위의 님의 코딩예 처럼 말이죠....
^^;; 지금의 저의 수준으로는 쉽지가 않습니당. .
2번의 문제는 block socket으로 하면 어느정도 해결되지 않을까 생각이 드는데.. 맞을까요~?
댓글 달기