i/o multiplexing & nonblocking socket, multi-thread 질문

sunbee의 이미지

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()으로 잠깐의 여유(?)를 주니까 올바른 동작을 하더군요.. 왜 이런겁니까~?

가르침을 주소서~ ^_^

kane의 이미지

1. read event 감지 -> 감시 대상에서 제외 -> 소켓 전달 -> read 및 작업 (io thread는 event 감시 중)-> 소켓 되돌려주기 -> 감시 대상에 포함 -> read event 감지
순으로 하면 우선순위는 문제가 될 것 같지 않습니다만..

2. 코드가 없으면 어떤 문젠지 알기 힘들 것 같네요.

hanzo69의 이미지

우선 2번.
혹시 i/o thread에서 select, poll 을 하실때 타임아웃을 0으로 하고 무작정 루프를 돌리신겁니까?

while( 1 ) {
    // 이렇게 이벤트가 없으면 다시 재시도하도록...
    if( select(  ) == 0 ) {
        // 그나마 이렇게 갭을 주면 나아지긴 하지만 별로...
        // usleep(); 
        continue; 
    }
    recv();
}

usleep()으로 잠깐의 여유를 주셨다는걸 보면... 아마 select, poll을 가지고 이벤트를 대기하는게 아니라 체킹하는데 쓰신 듯 합니다만.

만약 그런거라면..
비선점형, 선점형을 떠나 어플리케이션의 쓰레드가 그렇게 쉴 새 없이 돌아갈 경우 커널의 작업이 방해받을 수 있습니다.
순위역전이 발생하여 수신된 패킷을 처리하고 이벤트를 만들어야 할 커널 대신 쉴 새 없이 돌아가는 응용프로그램이 자원을 더 오래 독점하기때문이죠.
할 일이 없을 때 반드시 쉬고, 할 일이 있는 시간만 일하도록 만드는게 가장 이상적인 방법입니다. 그리고 할 일이 꾸준히 있다 하더라도 타 프로세스/쓰레드와의 동시 실행관계를 살펴 적절히 yield를 하게 만들어야 합니다.

1번...
TCP 서버 개발에서 i/o demuxing은 단순히 수신 이벤트만 감지하기 위한건 아닙니다. reactor의 경우 송신 재개 가능 이벤트, proactor의 경우 송신 완료 이벤트를 감지하려는 목적도 있죠.

저같은 경우엔 보통

(이벤트 감지 - 전송 처리 - 모델 처리)

의 세가지 분류를 기본으로 설계합니다.

암튼 지금 돈 받고 일하시는게 아니라 개인적으로 공부하시는거라면...
여러가지 방식으로 시도를 해 보시는게 좋을 듯 합니다^_^;
말씀하신 그런 방식도 나쁘진 않겠네요..
가장 효율적인 방식은... 각 상황에 맞는 방식이죠. 그걸 알기 위해선 끊임없는 시도가 필요할테구요.
어떤 고정적인 틀을 잡고 이대로만 한다는 식으로 하면... 결국 STL처럼 본말이 전도되는 결과를 만들어내니까요.

님ㅎ 즐~

익명 사용자의 이미지

답변 감사드립니당.. ^^

1

Quote:

read event 감지 -> 감시 대상에서 제외 -> 소켓 전달 -> read 및 작업 (io thread는 event 감시 중)-> 소켓 되돌려주기 -> 감시 대상에 포함 -> read event 감지

kane님께서 말씀하신 방법 괜찮아 보입니다.
하지만 i/o thread와 read thread간에 fd_set을 위한 별도의 동기화 과정이 필요할듯 보입니다.
그리고, 테스트를 해보진 않았지만 효율적인 면에서는 떨어지지 않을까 생각이 드는데요..
select(..)의 예를 들면 감시대상에서 제외(FD_CLR(..)), 감시대상에포함(FD_SET(..)) 행위를 계속 해줘야 하니까요...
한번 테스트 해봐야 겠군요...^^

2.

Quote:

혹시 i/o thread에서 select, poll 을 하실때 타임아웃을 0으로 하고 무작정 루프를 돌리신겁니까?
usleep()으로 잠깐의 여유를 주셨다는걸 보면... 아마 select, poll을 가지고 이벤트를 대기하는게 아니라 체킹하는데 쓰신 듯 합니다만.

timeout을 0으로 주지않았습니다.
int listen_CPort(int searchfd, fd_set *allfds)
{
    int ret_val = 0;
    static  struct timeval  timeout;

    timeout.tv_sec  = (10 / 1000);
    timeout.tv_usec = (10 % 1000) * 1000;

    ret_val = select(searchfd + 1, (fd_set *)allfds, (fd_set *)0,
                   (fd_set *)0, (struct timeval *)&timeout);

    return ret_val;
}

Quote:

usleep()으로 잠깐의 여유를 주셨다는걸 보면... 아마 select, poll을 가지고 이벤트를 대기하는게 아니라 체킹하는데 쓰신 듯 합니다만.

맞습니다..
block이 아니라 nonblock 입니다. 체킹하는거죠...
위의 님의 코딩예 처럼 말이죠....

Quote:

할 일이 없을 때 반드시 쉬고, 할 일이 있는 시간만 일하도록 만드는게 가장 이상적인 방법입니다. 그리고 할 일이 꾸준히 있다 하더라도 타 프로세스/쓰레드와의 동시 실행관계를 살펴 적절히 yield를 하게 만들어야 합니다.

^^;; 지금의 저의 수준으로는 쉽지가 않습니당. .

2번의 문제는 block socket으로 하면 어느정도 해결되지 않을까 생각이 드는데.. 맞을까요~?

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.