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

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

꾸준함. 2017. 6. 15. 20:27

1. 다음 중 프로세스에 대한 설명으로 옳은 것은?


>a. 프로세스는 운영체제의 관점에서 프로그램의 실행 단위가 된다.

  b. 프로세스도 생성방식에 따라서 부모와 자식의 관계를 갖는다


*틀린 설명

c. 프로세스는 다른 프로세스를 포함할 수 있다. 즉, 하나의 프로세스는 자신의 메모리 영역에 또 다른 프로세스를 포함할 수 있다.

->프로세스는 독립적인 존재이다. 다른 프로세스를 포함할 수 없다.


d. 자식 프로세스는 또 다른 자식 프로세스를 생성할 수 있고, 이렇게 생성된 자식 프로세스 역시 또 다른 자식 프로세스를 생성할 수 있지만, 이들은 모두 하나의 프로세스와만 부모자식의 관계를 형성한다.

->하나의 프로세스와만 부모자식의 관계를 형성하는 것은 맞지만, 자식프로세스가 다른 자식 프로세스를 생성할 수는 없다.


2. fork 함수가 호출되면 자식 프로세스가 생성되는데, 이 자식 프로세스의 특징으로 옳은 것을 모두 고르면?


>b. 자식 프로세스는 부모 프로세스의 모든 것을 복사해서 생성되는 프로세스이다.


*틀린 설명

a. 부모 프로세스가 소멸되면 자식 프로세스도 소멸된다

->함수호출 이후에 부모 프로세스와 자식 프로세스가 서로 완전히 분리된 메모리 구조를 지닌다


c. 부모 프로세스와 자식 프로세스는 전역으로 선언되는 변수를 공유한다.

->자식 프로세스에서 전역변수를 증가시킨다 해도 부모 프로세스에 영향을 주지 않는다.


d. fork 함수 호출로 생성된 자식 프로세스는 부모 프로세스가 실행한 코드를 처음부터 fork 함수가 호출된 위치까지 실행해 온다.

->두 프로세스 모두 fork 함수의 호출 이후 문장을 실행하게 된다(정확히 표현하면 fork 함수의 반환 이후)


3. 자식 프로세스가 생성되면 부모 프로세스의 모든 것을 복사하는데, 이 때 복사의 대상으로는 소켓의 파일 디스크립터도 포함이 된다. 그렇다면 복사된 파일 디스크립터의 정수 값은 원본 파일 디스크립터의 정수 값과 동일한지 확인하기 위한 프로그램을 작성해보자.


>

[리눅스 버전](멀티 프로세서 기반 서버구현은 리눅스에 중점을 둔 이야기라 리눅스 코드만 있다)

#include <stdio.h>

#include <unistd.h>

#include <sys/socket.h>

 

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

{

        pid_t pid;

        int sockfd = socket(PF_INET, SOCK_STREAM, 0);

 

        pid = fork(); //fork 함수

 

        if (pid == 0) //자식 프로세스라면

               printf("Child sock fd: [%d] \n", sockfd);

        else //부모 프로세스라면

               printf("Parent sock fd: [%d] \n", sockfd);

        return 0;

}


 [파일 디스크립터의 값이 동일한 것을 볼 수 있다]


4. 프로세스가 좀비가 되는 경우에 대해 설명하고, 이를 막기 위해서 어떠한 방법을 취해야 하는지 설명해 보자


>좀비가 되는 프로세스는 자식 프로세스이다. 자식 프로세스 종료시 인자로 전달 및 반환되는 값은 운영체제로 넘어가는데, 이 값이 자식 프로세스의 부모 프로세스에게 전달되기 전까지 해당 자식 프로세스는 좀비 프로세스가 된다. 따라서 이를 막기 위해서는 부모 프로세스가 자식 프로세스의 종료 값을 명시적으로 요청해야 하며, 이 값이 부모 프로세스에게 전달되고 나면 자식 프로세스는 소멸이 되어서 좀비로 남아있지 않게 된다.


5. SIGINT에 대한 핸들러를 등록하지 않은 상태에서 Ctrl+C 키가 입력되면, 운영체제가 지정해 놓은 디폴트 이벤트 핸들러에 의해서 프로그램이 종료되어 버린다. 그러나 Ctrl+C 키에 대한 핸들러를 직접 등록하면 프로그램은 종료되지 않고 프로그래머가 지정한 이벤트 핸들러가 대신 호출된다. 그렇다면 일반적인 프로그램에서 다음과 같이 동작하도록 이벤트 핸들러 등록을 위한 코드를 구성해 보자.

"Ctrl+C 키가 눌리면, 정말로 프로그램을 종료할 것인지 묻고, 이에 대한 대답으로 'Y'가 입력되면 프로그램을 종료한다"

그리고 간단히 문자열을 1초당 한번 정도 반복 출력하는 프로그램을 작성해서 위의 이벤트 핸들러 등록 코드를 적용시켜보자


>

[리눅스 버전](멀티 프로세서 기반 서버구현은 리눅스에 중점을 둔 이야기라 리눅스 코드만 있다)

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <signal.h>

 

void ctrl_handler(int sig);

 

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

{

        struct sigaction act; //signal 함수보다 안정적

        act.sa_handler = ctrl_handler;

        sigemptyset(&act.sa_mask);

        act.sa_flags = 0;

        sigaction(SIGINT, &act, 0);

 

        while (1)

        {

               sleep(1);

               puts("Have a nice day~");

        }

 

        return 0;

}

 

 

void ctrl_handler(int sig)

{

        char sel;

        fputs("Do you want to exit(press Y to exit)? ", stdout);

        scanf("%c", &sel);

        if (sel == 'y' || sel == 'Y')

               exit(1);

}

 


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

반응형