i/o multiplexing & thread 에서..

sunbee의 이미지

nonblocking 소켓입니다.
main thread에서 io_thread를 하나 생성하고,
io_thread에서 work_thread를 여러개 생성하였습니다.

io_thread는 select() 하고 데이타를 recv() 합니다.
그리고나서 놀고있는 work_thread를 찾아 recv한 데이타를 넘깁니다.

/* work thread */
struct {
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int ready;
    int sfd;                              /* 이벤트 발생한 소켓 */
    int status;                         /* 1 is running, 0 is sleep */
    char buff[MSG_BUFFER];
}WK_thread[MAXNTHREADS];

위와 같이 work_thread는 work_thread당 buffer를 두기 위해 배열로 만들었습니다.

근데!!! 문제점은
io_read_thread 에서 select()를 잘 못합니다..(?) 무슨 말인고 하니.. 여러개의 client가 접속을 해도 하나의 client 소켓 event만 return 합니다. i/o multiplexing을 못한단 말이죠...

뭐가 문젠지 잘 모르겠습니당.. 왜 이런거죠~?

대충의 코드 구조입니다.

io_thread

        /*
        ** i/o multiplexing
        */
        select(....);

        /* packet read */
        if((ret_val = read_packetC(event_fd)) < 0) {
            /* disconnect work */
            .....
        }

        /* 휴면 스레드를 찾는다. */
        for(free_tid = 0; free_tid < MAXNTHREADS; free_tid++) {
            if(WK_thread[free_tid].status == 0) {
                memcpy(WK_thread[free_tid].buff, (user_buff +5), readed_len);

                packet_len = 0;
                readed_len = 0;
                memset(user_buff,  '\0', MSG_BUFFER);
                break;
            }
        }

        /*
        ** work thread를 깨운다.
        */
        pthread_mutex_lock(&(WK_thread[free_tid].mutex)); 
       
        /*
        ** event가 발생된 socket을 세팅한다.
        */
        WK_thread[free_tid].sfd = event_fd;

        if(WK_thread[free_tid].ready == 0) {
            pthread_cond_signal(&(WK_thread[free_tid].cond));
        }
        WK_thread[free_tid].ready = 1;


        /* thread full ~~~~~ */
        if(RD_WK_thread_count >= MAXNTHREADS) {
                ;
        }

        pthread_mutex_unlock(&(WK_thread[free_tid].mutex));
익명 사용자의 이미지

select()를 호출하여 리턴값이 0이상이면, 현재 접속되어 있는 소켓들에 대해 루프를 돌면서 FD_ISSET()을 이용해 읽기, 쓰기, 예외처리 등의 작업을 해 줘야 하는데 그 부분이 안보이네요?

익명 사용자의 이미지

혹시 이런문제가 아니신지?
옛날에 저도 고생한 부분인데..
select 한후에 fdset은 select 전의 fdset과 달라집니다.
따라서 계속적으로 while로 select를 한다면 먼저 fdset값을
저장해 놓구 select 를 한후에 다시 fdset값을 채워야 합니다.

이 문제가 아니라면 죄송.. ..

sunbee의 이미지

답변 감사드립니다.

Quote:

select()를 호출하여 리턴값이 0이상이면, 현재 접속되어 있는 소켓들에 대해 루프를 돌면서 FD_ISSET()을 이용해 읽기, 쓰기, 예외처리 등의 작업을 해 줘야 하는데 그 부분이 안보이네요?

이부분은 모듈화 시켜놓았구요.. i/o multiplexing에는 전혀 문제가 없습니당...

위부분은 대략적인 코딩구조입니당...
사실 select()로 개발한게 아니라 /dev/poll 을 이용하였거던요...이해하기 쉽게 그냥 select()라고 말씀드린겁니다...
OS 는 솔라리스입니당...

IsExist의 이미지

pseudo 코드로 봐서는 한번에 한개의 recv만 처리하네요.
recv할 개 2개의 fd가 발생할 경우 2개를 차례로 io_thread가
read_packetC 해야 할거 같네요. 그리고 그걸 놀고 있는 WK_thread
한테 복사해 줘야 겠죠. (만약 read_packetC가 2개를 다 한다면
밑에 for 루프에서 memcpy 를 두번 하던지). 혹 io_thread가 두개
이상은 아니겠죠??

recv를 io_thread 하고 다시 각 일을 맡길 thread 한태 memcpy
로 복사하니 메모리 복사가 두번 생깁니다. 이거 불필요 한겁니다.
복사할 내용이 작다면 영향을 미미 하겠지만요.

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치