C/TCPIP 소켓 프로그래밍(윤성우 저)

TCP/IP 소켓 프로그래밍 18장 내용 확인문제

꾸준함. 2017. 7. 23. 20:18

1. 하나의 CPU를 기반으로 어떻게 둘 이상의 프로세스가 동시에 실행되는지 설명해보자. 그리고 그 과정에서 발생하는 컨텍스트 스위칭이 무엇인지도 함께 설명해보자.


>CPU의 실행시간을 프로세스가 고속으로 나누기 때문에 둘 이상의 프로세스가 동시에 실행 가능하다. 그리고 컨텍스트 스위칭이란, CPU에 의한 실행의 대상을 변경하는 과정에서 발생하는 준비과정으로써, 이전에 실행되던 프로세스의 데이터를 메모리 공간에서 내리고 이어서 실행될 프로세스의 데이터를 메모리 공간 위에 올리는 작업이다.


2. 쓰레드의 컨텍스트 스위칭이 빠른 이유는 어디에 있는가? 그리고 쓰레드간의 데이터 교환에는 IPC와 같은 별도의 기법이 불필요한 이유는 무엇인가?


>쓰레드 각각의 고유 데이터는 프로세스 각각의 고유 데이터보다 크기가 작다. 따라서 컨텍스트 스위칭의 과정에서 올리고 내릴 데이터의 크기가 그만큼 작으며, 이로 인해서 프로세스의 컨텍스트 스위칭보다 속도가 빠르다. 또한 모든 쓰레드는 스택을 제외한 나머지 메모리 공간을 공유하기 때문에 IPC와 같은 별도의 통신 기법이 필요하지 않다.


3. 실행흐름의 관점에서 프로세스와 쓰레드를 구분하여라.


>프로세스는 운영체제 관점에서의 실행흐름을 의미하고, 쓰레드는 프로세스 내에서 구분되는 실행흐름을 의미한다.


4. 다음 중에서 임계영역과 관련해서 맞게 설명하고 있는 것을 모두 고르면?


>

a. 임계영역은 둘 이상의 쓰레드가 동시에 접근(실행)하는 경우에 문제가 발생하는 영역을 의미한다.


*틀린내용

b. 쓰레드에 안전한 함수는 임계영역이 존재하지 않아서 둘 이상의 쓰레드가 동시에 호출해도 문제가 발생하지 않는 함수를 의미한다.

-> 쓰레드에 안전한 함수도 임계영역이 존재할 수 있다.


c. 하나의 임계영역을 하나의 코드블록으로만 구성된다. 하나의 임계영역이 둘 이상의 코드블록으로 구성되는 경우는 없다. 즉, A 쓰레드가 실행되는 코드블록 A와 B 쓰레드가 실행되는 코드블록 B 사이에서는 절대 임계영역이 구성되지 않는다.

->쓰레드 동기화를 진행하지 않는다면 둘 이상의 코드블록으로 구성될 가능성이 있다


d. 임계영역은 전역변수의 접근코드로 구성된다. 이외의 변수에서는 문제가 발생하지 않는다.

->꼭 전역변수가 아니더라도 동시에 접근 가능한 메모리가 있다면 문제가 발생한다.


5. 다음 중에서 쓰레드의 동기화와 관련해서 맞게 설명하고 있는 것을 모두 고르면?


>

a. 쓰레드의 동기화는 임계영역으로의 접근을 제한하는 것이다.

b. 쓰레드의 동기화에는 쓰레드의 실행순서를 컨트롤한다는 의미도 있다.

c. 뮤텍스의 세마포어는 대표적인 동기화 기법이다.


*틀린내용

d. 쓰레드의 동기화는 프로세스의 IPC를 대체하는 기법이다.

->모든 쓰레드는 스택을 제외한 나머지 메모리 공간을 공유하기 때문에 IPC와 같은 별도의 통신 기법이 필요하지 않다.


6. 리눅스의 쓰레드를 완전히 소멸하는 방법 두 가지를 설명하여라


>pthread_join/pthread_detach 함수 둘 중 하나를 호출하여 명시적으로 쓰레드의 완전소멸을 명시해야한다.


7. 에코 서버를 멀티쓰레드 기반으로 구현해보자. 단, 클라이언트가 전송하는 메시지의 저장을 목적으로 선언되는 메모리 공간(char형 배열)을 모든 쓰레드가 공유하도록 하자.


>

[멀티쓰레드 기반 에코 서버]

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>

#include <sys/select.h>

#include <pthread.h>

 

#define BUF_SIZE 100

void * handle_clnt(void * arg);

void error_handling(char *buf);

 

char buf[BUF_SIZE];

pthread_mutex_t mutx;

 

int main(int argc, char *argv[])

{

        int serv_sock, clnt_sock;

        struct sockaddr_in serv_adr, clnt_adr;

        int clnt_adr_sz;

        pthread_t t_id;

 

        if(argc!=2) {

               printf("Usage : %s <port>\n", argv[0]);

               exit(1);

        }

 

        pthread_mutex_init(&mutx, NULL);

        serv_sock=socket(PF_INET, SOCK_STREAM, 0);

        memset(&serv_adr, 0, sizeof(serv_adr));

        serv_adr.sin_family=AF_INET;

        serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);

        serv_adr.sin_port=htons(atoi(argv[1]));

       

        if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)

               error_handling("bind() error");

        if(listen(serv_sock, 5)==-1)

               error_handling("listen() error");

 

        while(1)

        {

               clnt_adr_sz=sizeof(clnt_adr);

               clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr,&clnt_adr_sz);

               pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock);

               pthread_detach(t_id);

               printf("Connected client IP: %s \n", inet_ntoa(clnt_adr.sin_addr));

        }

 

        close(serv_sock);

        return 0;

}

 

void * handle_clnt(void * arg)

{

        int clnt_sock=*((int*)arg);

        int str_len=0;

       

        while(1)

        {

               pthread_mutex_lock(&mutx);

               str_len=read(clnt_sock, buf, sizeof(buf));

               if(str_len<=0)

                       break;

               else

                       write(clnt_sock, buf, str_len);

               pthread_mutex_unlock(&mutx);

        }

       

        close(clnt_sock);

        return NULL;

}

void error_handling(char *buf)

{

        fputs(buf, stderr);

        fputc('\n', stderr);

        exit(1);

}


8. 위의 문제 7에서는 에코 메시지의 송수신에 사용할 메모리 공간을 모든 쓰레드가 공유할 것을 요구하고 있다. 이렇게 구현을 하면 동기화를 해도, 안해도 문제가 발생하는데, 각각의 경우에 따라서 어떠한 문제가 발생하는지 설명해 보자.


>동기화를 하지 않으면 둘 이상의 쓰레드가 메모리 공간에 동시에 접근을 해서 문제를 일으킨다. 반면 동기화를 해버리면, 임계영역에 포함되어야 하는 read 함수의 호출문장으로 인해서 다른 클라이언트가 전송하는 문자열을 읽어들이지 못하고 대기해야만 하는 상황이 벌어진다.


[참고] TCP/IP 소켓프로그래밍 윤성우 저

반응형