티스토리 뷰
서로다른 Process간에 통신을 하기위해서는 IPC, RPC등의 기법들을 이용해야하는데 이번 포스팅에서는 IPC기법에는 어떤 것들이 있고, 각자 사용되는 상황 및 특징들을 살펴보겠다.
<종류>
1. Anonymous PIPE (익명 파이프)
2. Named PIPE
3. Message Queue
4. Shared Memory
5. Socket - 해당 포스트에서는 따로 다루지 않습니다. 워낙 뭐.. ㅎㅎ
6. .....
위 5개는 확실하게 알고가자!!
1. Anonymous PIPE
- 외부 프로세스에서는 이 파이프에 접근이 불가능하다.
But, fork등의 방법으로 자식프로세스가 태어난 경우에는 File Descriptor를 상속받아 통신가능.
int fd[2];
rc = pipe(fd); → 0번 index에는 stdin, 1번 index에는 stdout의 stream이 할당된다.
( Return값이 0보다 커야 정상. )
- 특수한 경우에는 최고의 간단한 구성.
그러나 적용가능한 범위가 굉장히 제한적이다.
- PIPE에 Data가 들어가는 순간, 주인없는 Data가 된다.
- 양방향 통신을 위해서라면 두개의 파이프가 필요하다. 하나로는 절대안됌!!
2. Named PIPE
- Anonymous PIPE의 한계인 외부프로세스와의 통신을 위한 파이프.
( mkfifo, mknod를 통해 pipe 파일을 생성하고, 그 파일을 통해 통신 )
int fd = open("./pipe_name", O_WRONLY); write(fd, Buffer, sizeof(Buffer));
---------------------------------------------------
access("./pipe_name", O_OK) → unlick("./pipe_name"); rc = mkfifo("./pipe_name", 0666); int fd = open("./pipe_name", O_RDWR); read(fd, Buffer, sizeof(Buffer));
|
각각 프로세스에서 위와같이 구성을하게되며 mkfifo는 반드시 한쪽에서만 해줘야한다.
- 하나의 파이프를 통해 양방향 통신이 가능은하다.
그러나, PIPE에 들어가는순간 임자없는 데이터가되고 넣은애가 도로 꺼내갈수도있다.
그러므로 그냥 속편하게 두개의 PIPE를 사용하는 것이 낫다.
3. Message Queue
- 어디에서든 Message를 꺼낼수 있는 공간. 즉, 메모리공간을 이용해 통신한다.
- 데이터에 Message번호를 붙여서 서로를 인식할 수 있다.
- 사용자가 임의로 만든 구조체를 단위로 데이터를 송/수신한다.
( 해당 구조체는 송/수신하는 두군데에 전부 정의해줘야한다. )
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
int msgsnd(int msgid, const void* msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msgid, void* msgp, size_t msgsz, long msgtyp, int msgflg);
구현.
typedef struct{ long msgtype; char msg_text[100]; }Msg; → 구조체를 통해 메세지를 구성하게되는데 long msgtype만 고정이고 나머진 자유롭게 구성.
key_t key = 4449; int que_id = msgget(key, IPC_CREAT | 0666); → 여기서 key값을 통해 해당 Queue를 생성(?)한다. ( 연결이라는 표현이 적절할지도..? ) 즉, 반드시 메세지를 주고받으려는 프로세스들끼리 일치시켜줘야한다.
Msg msg; int msg_size = 0; msg.msgtype = 10831; → 이것도 반드시 일치시켜줘야한다. 이건 해당 큐에서도 메세지의 종류를 여러개로 세분화하기위함 !! strcpy(msg.msg_text, "ch4njun's data"); msg_size = sizeof(msg) - sizeof(msg.msgtype); → msg의 크기는 반드시 long msgtype의 크기를 제외한 크기여야한다. msgsnd(que_id, &msg, msg_size, 0);
꺼내는건 ! msgrcv(que_id, &msg, msg_size, 10831, IPC_NOWAIT);
msgctl(que_id, [ FLAG ], struct msqid_ds* buf); - IPC_STAT, IPC_SET, IPC_RMID ( IPC_RMID는 해당 Message Queue를 삭제한다. 떄문에 3번째 파라미터는 NULL )
|
4. Shared Memory
- 공유메모리가 데이터자체를 공유하도록 지원.
- 기본적으로 모든 프로세스는 자신만의 메모리 영역을 가진다. 그리고 그 영역은 커널로부터 보호되어진다. 다른 프로세스에서 함부로 그 메모리 영역에 접근하지 못하도록 보호되어진다. 이 때 PIPE와 같이 STREAM이 아니라 메모리자체를 공유하고 싶다면 커널에 요청하면 커널은 해당 프로세스에 공유 메모리 공간을 할당해준다. 이 메모리는 모든 프로세스가 중계자(커널)없이 접근이 가능해 IPC들 중에서 가장 빠르게 동작한다.
int shmid = shmget((key_t)1234, 1024, IPC_CREAT | 0666); → Key, Size 둘다를 반드시 양쪽에서 동일하게 해줘야 한다... (솔직히 size는 TMI긴해) void* shmaddr = shmat(shmid, (void*)0, 0); → shmaddr 이라는 Stack변수에 공유메모리할당받은 주소를 저장하는거지. 그리고 그 주소에 shmaddr이라는 Stack변수를 통해서 접근하는거야 ! strcpy((char*)shmaddr, "ch4njun's data"); shmdt(shmaddr);
int shmid = shmget((key_t)1234, 1024, IPC_CREAT | 0666); void* shmaddr = shmat(shmid, (void*)0, 0); printf("%s\n", (char*)shmaddr); shmdt(shmaddr);
공유메모리를 제거하고 싶을 땐, shmdt(shmaddr); 을 통해 해당 프로세스에서 공유메모리를 분리하고. shmctl(shmid, IPC_RMID, 0); 명령을 통해서 제거하면된다.
|
'운영체제(OS)' 카테고리의 다른 글
[OS] 다중 처리기 스케줄링 (0) | 2019.11.04 |
---|---|
[OS] CPU Scheduling 기본 ( 6가지 ) (0) | 2019.11.04 |
[OS] CPU Scheduling (0) | 2019.09.30 |
[OS] Process Synchronized (0) | 2019.09.07 |
[OS] Thread (0) | 2019.09.07 |