본문 바로가기

CS/O.S

(운영체제) 다양한 IPC 기법 (파이프, 메세지큐)

PIPE (파이프)

fork() 시스템 콜을 호출하면 새로운 프로세스를 복제하는데 굳이 왜 그렇게 하는 것이지?

 

fork()의 리턴 값은 정수형을 반환한다.

  • 부모 프로세스 : 프로세스 ID
  • 자식 프로세스 : 0
char * msg = "Hello Child Process";

int main(int argc, char const *argv[])
{
	/* code */

	char buf[255];
	int fd[2], pid, nbytes;
	if (pipe(fd) < 0)		//pipe(fd) 로 파이프 생성
	{
		/* code */
		exit(1);
	}
	pid = fork();	// 이 함수 실행 다음 코드부터 부모/자식 프로세스로 나뉘어짐

	if (pid > 0)	// 부모 프로세스는 pid에 실제 프로세스 ID가 들어감
	{
		/* code */
		write(fd[1], msg, MSGSIZE);  // fd[1] 에 씁니다.
		exit(0);
	}else {		// 자식 프로세스는 pid가 0이 들어간다.
		mbytes = read(fd[0], buf, MSGSIZE);		//fd[0] 으로 읽음
		printf("%d %s\n", nbytes, buf);
		exit(0);
	}

	return 0;
}

부모 프로세스에서 write를 하고 자식 프로세스에서는 read를 하는 점에 주목하자!😀

(msg -> buf)

 

다른 프로세스임에도 불구하고 서로 통신을 한다는 점이 핵심이다.

 

기본 파이프는 단방향 통신이다.
fork()로 자식 프로세스를 만들었을 때, 부모와 자식 간의 통신이 시작된다.

메시지 큐 (Message queue)

기본은 FIFO 정책으로 데이터를 전송한다.

http://www.stoimen.com/2017/09/14/data-structures-infographic-stack-queue/

 

stoimen's web log

 

www.stoimen.com

A Process

msqid = msgget(key, msgflg);
msgsnd = (msqid, &sbuf, buf_length, IPC_NOWAIT);

특별한 key를 생성하여 메시지 큐에 담고 sbuf에 넣어 msgsnd함수를 이용하여 큐에 INSERT 한다.

 

B Process

msqid = msgget(key, msgflg);
msgsnd = (msqid, &rbuf, MSGSZ, 1, 0);

동일한 key를 사용하여 해당 큐의 msgid를 얻을 수 있다.

 

파이프와 메시지 큐의 차이점

파이프와는 다르게 메시지 큐는 fork() 시스템 콜이 필요 없다. (key 값만 동일하면 된다.)

파이프와는 다르게 메시지 큐는 양방향 통신이 가능하다.

 

IPC 기법과 커널 모드

파이프, 메시지 큐 모두 커널 공간의 메모리를 사용한다.

 

공유 메모리

노골적으로 커널 공간에 공유할 수 있는 메모리 공간을 만들고 해당 공간을 변수처럼 사용하는 방식

공유 메모리 Key를 가지고 해당 메모리에 여러 프로세스가 접근이 가능하다.