2016년 5월 22일 일요일

뇌자극 TCP_IP 프로그래밍 11강 요약 1

1. IPC에 대하여

컴퓨터 내부의 프로세스들이 서로 데이터를 주고 받을 수 있는 것
IPC는 그 자체가 도구가 아닌 '내부 통신을 위한 여러 도구'의 총칭이다
IPC 설비에서 제공하는 도구는 다음과 같다

파이프, 메시지 큐, 네임드 파이프, 공유 메모리,
메모리 맵, 시그널, 세마포어, 유닉스 도메인 소켓

2. 파이프 - 익명 파이프와 네임드 파이프

IPC 설비가 제공하는 내부통신 도구 중 가장 널리 사용되는 도구는 파이프다.
파이프는 프로세스 간의 파이프 모양의 단반향 통신 선로를 개설한다.
읽기 쓰기를 모두 수행하려면 두 개의 파이프를 만들어야 한다.

단방향 통신 : 한 반향으로만 통신 가능. 파이프
반이중 통신 : 양쪽 방향으로 통신이 가능 하지만, 동신 퉁신은 불가능. 무전기
전이중 통신 : 동시에 양쪽 방향을 통신 가능. 전화기, 소켓

파이프 만들기 
#include <unistd.h>
int pipe(int filedes[2]);

fileds : pipe 함수를 실행하면 매개변수로 파이프를 가리키는 파일 지정 번호를 돌려준다.

filedes[0] 은 읽기 전용, filedes[1] 는 쓰기 전용 파이프다.
이 두 파이프로 전이중 통신을 구현한다.

파이프는 부모 프로세스 <-> 자식 프로세스 통신을 위해 사용된다.

파이프 예제

//pip 함수로 파이프를 만든다.
        if (pipe(fd) < 0)
{
perror("pipe error : ");
return 1;
}
//fork 함수로 자식 프로세스를 생성한다.
if ((pid = fork()) < 0)
{
return 1;
}
// 만약 자식프로세스라면 파이프에 자신의 PID 정보를 쓴다.
else if (pid == 0)
{
close(fd[0]); //읽기 전용 파이프 닫기 
while(1)
{
i++;
write(fd[1], (void *)&i, sizeof(i)); //쓰기 전용 파이프
sleep(1);
}
}

// 만약 부모프로세스라면 파이프에서 데이터를 읽어 들인다.
else
{
close(fd[1]); //쓰기 전용 파이프 닫기
while(1)
{
read(fd[0], (void *)&buf, sizeof(buf)); //읽기 전용 파이프
printf("> %d\n", buf);
}
}

익명 파이프와 네임드 파이프

내부 통신을 위해서 사용할 수 있는 가장 간단한 도구는 파일이다.
파이프와 파일의 가장 큰 차이는 '이름'을 가지고 있는지 여부다.
pipe 함수로 만든 파이프는 이름을 가지고 있지 않기에
외부의 프로세스는 이 파이프를 사용할 수 없다.
파이프는 부모/자식 프로세스 간에만 사용할 수 있다.
외부 프로세스와 파이프 통신을 하기 위해서는 파이프에 이름을 지어주면 된다.

네임드 파이프의 생성

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

pathname : 네임드 파이프의 이름이다. 네임드 파이프는 파일 형태다. 파일이므로 이름만으로도 어디에서나 파이프에 접근할 수 있다.
mode : 파일이므로 권한을 설정해야 한다.

네임드 파이프의 예제

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>

#include <unistd.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 1024
int main(int argc, char **argv)
{
int rfd, wfd;
char buf[MAXLINE];
//mkfifo 함수로 네임드 파이프를 만든다.
mkfifo("/tmp/myfifo_r", S_IRUSR|S_IWUSR);  //읽기용 네임드 파이프
mkfifo("/tmp/myfifo_w", S_IRUSR|S_IWUSR);  //쓰기용 네임드 파이프
//네임드 파이프를 연다
        if( (rfd = open("/tmp/myfifo_r", O_RDWR)) == -1)
{
perror("rfd error");
return 0;
}
if ( (wfd = open("/tmp/myfifo_w", O_RDWR)) == -1)
{
perror("wfd error");
return 0;
}
//읽기 네임드 파이프에서 데이터를 읽어서 쓰기 네임드 파이프에 쓴다.
while(1)
{
memset(buf, 0x00, MAXLINE);
if(read(rfd,buf,MAXLINE) < 0)
{
perror("Read Error");
return 1;
}
printf("Read : %s", buf);
write(wfd, buf, MAXLINE);
//쓰기 버퍼를 비워서 즉시 파일에 쓰도록 한다. 파일 내에서 위치를 재정의 하는 함수다.
lseek(wfd, 0, SEEK_SET);
}
}

3. 유닉스 도메인 소켓

IPC와 네트워크 통신은 통신 영역만 다를 뿐 본질적으로 차이가 없다.
소켓으로도 내부 프로세스 간 통신을 할 수 있다.

소켓 함수에서 첫번째 매개 변수를 바꾸면 가능하다
int socket(int domain, int type, int protocol);

struct sockaddr_un sockaddr;
socket (AF_UNIX, SOCK_STREAM, 0);
strncpy(serveraddr.sun_path, "filename", 8);

유닉스 도메인 소켓의 용도

유닉스 도메인 소켓 방식은 소켓 함수 뿐만 아니라 소켓 프로그래밍 모델까지 그대로 사용할 수 있다. 간단히 서버/클라이언트 모델을 구현할 수 있다.
대신, 파이프에 비해서 성능이 약간 떨어진다.
데이터를 가공하기 위한 여러 프로세스로 구성된 미들웨어와 같은 큰 규모의 프로그램에서 내부 데이터 통신을 원한다면 유닉스 도메인 소켓을 사용하길 권장한다.

소스 코드 보기

댓글 없음:

댓글 쓰기