모든 내용은 [윤성우 저, "열혈강의 TCP/IP 소켓 프로그래밍", 오렌지미디어] 를 기반으로 제 나름대로 이해하여 정리한 것입니다. 다소 부정확한 내용이 있을수도 있으니 이를 유념하고 봐주세요!
01. 프로세스간 통신이 의미하는 바는 무엇인가? 이를 개념적으로, 그리고 메모리의 관점에서 각각 설명해보자
# 프로세스간 통신의 기본 이해
- IPC가 가능하다는 것은 서로 다른 두 프로세스가 데이터를 주고받을 수 있다는 의미
- IPC가 가능하기 위해서는 두 프로세스가 동시에 접근 가능한 메모리 공간이 있어야 함
02. 프로세스간 통신에는 IPC라는 별도의 메커니즘이 요구된다. 그리고 이는 운영체제에 의해서 지원되는 별도의 기능이다. 그렇다면 프로세스간 통신에 있어서 이렇듯 운영체제의 도움이 필요한 이유는 무엇인가?
- 프로세스간 통신을 위해서는 공유되는 메모리가 필요하다. 그러나 본래 서로 다른 두 프로세스는 독립적으로 존재(메모리를 공유하지 않음)하기 때문에 운영체제의 도움이 필요하다. 따라서, 두 프로세스가 동시에 접근 가능한(공유하는) 메모리 영역을 운영체제가 제공해야 한다.
03. 대표적인 IPC 기법으로 '파이프(pipe)'라는 것이 있다. 파이프의 IPC 기법과 관련해서 다음 질문에 답해보자
a. 파이프는 프로세스간에 데이터를 송수신하는 경로를 의미한다. 그렇다면 이 경로는 어떻게 해서 생성되며, 누구에 의해 만들어지는가?
=> 파이프는 pipe 함수의 호출에 의해서 생성되며, 이러한 기능은 운영체제가 제공한다.
b. 프로세스간 통신을 위해서는 통신의 주체가 되는 두 프로세스 모두 파이프에 접근이 가능해야 한다. 그렇다면 하나의 파이프에 두 프로세스는 어떻게 해서 모두 접근이 가능한가?
=> pipe 함수호출에 의해 파이프가 생성이 되면, 파이프에 데이터를 입출력 하기 위한 파일 디스크립터 두개가 반환된다. 바로 이 파일 디스크립터를 fork 함수 호출 시 자식 프로세스에게 복사해줘서 부모 프로세스와 자식 프로세스 모두 파이프에 접근할 수 있게 된다.
c. 파이프는 두 프로세스간에 양방향 통신이 가능하게 한다. 그렇다면 양방향 통신을 진행하는데 있어서 특히 주의해야 할 사항은 무엇인가?
- "파이프에 데이터가 전달되면, 먼저 가져가는 프로세스에게 이 데이터가 전달된다."
- 즉, 파이프에 들어간 데이터는 주인이 따로 있는 것이 아니며, 먼저 가져간(읽어간) 프로세스가 임자
(혹여나 그 데이터가 자기자신이 전송한 데이터라도 먼저 읽어 들일 수 있음)
- 하나의 파이프만 이용하여 두 프로세스간에 양방향 통신을 하려면, 프로그램의 실행흐름을 예측하고 컨트롤해야 하는데 이는 시스템에 따라 다르기 때문에 사실상 불가능
=> 따라서 "파이프를 두 개를 생성"하여 프로세스간 양방향 통신을 하자.
04. IPC 기법을 확인하는 차원에서, 두 프로세스 사이에서 총 3회에 걸쳐서 문자열을 한번씩 주고받는 예제를 작성해 보자. 물론 두 프로세스는 부모, 자식의 관계로 형성이 되며, 주고 받을 문자열의 종류는 프로그램상에서 여러분이 임의로 결정하길 바란다.
# pipe3.c 의 응용
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUF_SIZE 30
int main(int argc, char* argv[])
{
int fds1[2], fds2[2], i;
char str1[]="Who are you?";
char str2[]="Thank you for your message.";
char str3[]="You're welcome!";
char *str_ary[]={str1,str2,str3};
char buf[BUF_SIZE];
pid_t pid;
pipe(fds1); pipe(fds2); // 두 개의 파이프 생성
pid=fork(); // 자식 프로세스 생성
if(pid==0) // 자식 프로세스의 경우
{
for(i=0;i<3;++i)
{
write(fds1[1],str_ary[i],strlen(str_ary[i])+1); // 1번 파이프를 통해 부모 프로세스에게 데이터 송신
read(fds2[0],buf,BUF_SIZE); // 2번 파이프를 통해 부모 프로세스에게 데이터 수신
printf("Child proc output: %s \n",buf);
}
}
else // 부모 프로세스의 경우
{
for(i=0;i<3;++i)
{
read(fds1[0],buf,BUF_SIZE); // 1번 파이프를 통해 자식 프로세스에게 데이터 수신
printf("Parent proc output: %s \n", buf);
write(fds2[1],str_ary[i],strlen(str_ary[i])+1); // 2번 파이프를 통해 자식 프로세스에게 데이터 송신
}
}
return 0;
}
[출처] : 윤성우 저, "열혈강의 TCP/IP 소켓 프로그래밍", 오렌지미디어
'Programming > 열혈 TCP, IP 소켓 프로그래밍(저자 윤성우)' 카테고리의 다른 글
Ch 12. 내용 확인문제 (0) | 2020.08.09 |
---|---|
Ch 12. IO 멀티플렉싱 (0) | 2020.08.09 |
Ch 11. 프로세스간 통신(Inter Process Communication) (0) | 2020.08.09 |
Ch 10. 내용 확인문제 (0) | 2020.08.08 |
Ch 10. 멀티프로세스 기반의 서버구현 (0) | 2020.08.08 |