시스템 V IPC (System V) 2 -InfiniteCS/시스템 프로그래밍2022. 6. 21. 01:57
Table of Contents
앞선 글에 이어서 이번 글에서는 Shared Memory와 Message Passing에 관한 간단한 소개 및 Shared Memory 방식에 대한 개념 및 예제를 알아보도록 하겠습니다.
● Shared Memory
-> 이는 공유 메모리이며 독립적인 프로세스들 간의 통신을 위해 공유되는 메모리 영역을 사용합니다.
-> 장점으로는 시스템 호출을 생성할 때(공유 메모리 생성)에 1번만 사용하기 때문에 매우 빠르며 효율이 좋습니다.
-> 단점으로는 모든 프로세스들이 접근 가능하기 때문에 Race Condition의 문제가 발생할 수 있으므로 동기화 과정이 필요합니다. 이는 세마포어를 이용하여 해결할 수 있습니다.
● Message Passing
-> 같이 쓴다의 개념이아닌 그때 그때 필요한 소스를 프로세스들 간에 파이프 등을 사용하여 전달하는 기법입니다.
-> 동기화를 고려할 필요가 없다는게 장점이지만, pipe생성 및 data복사로 인해 오버헤드가 발생하여 효율이 낮아지는 단점이 존재합니다.
● Shared Memory
-> 공유 메모리는 IPC 기법들 중에 가장 빠르고 효율이 좋은 통신 방식입니다.
공유 메모리를 사용하는데 필요한 함수에 대해서 알아보겠습니다.
1. 공유 메모리 생성 : shmget(key, size, shmflg) // shmflg는 주로 IPC_CREAT|0666이 사용됩니다.
2. 생성된 공유 메모리 연결 함수 : shmat(식별자, 연결할 주소, shmflg)
3. 연결된 메모리 해제 함수 : shmdt(공유 메모리의 시작주소)
4. 공유 메모리 제어 함수 : shmctl(식별자, 제어기능, 공유메모리 구조체 주소)
제어 함수의 매개변수로는 주로 IPC_RMID 메모리 해제 기능이 사용됩니다. 나머지 기능은 거의 쓰지않는다고 보시면 될 것 같습니다.
이번 공유메모리에 대해서는 곧바로 예제를 통해 확인해보도록 하겠습니다.
다음 예제는 두 개의 독립적인 프로세스가 하나의 공유메모리를 통해 실시간 채팅을 하는 프로그램입니다.
/* shm1.c */ 첫번째 독립 프로세스 - Client #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include "shm.h" // 헤더파일 int main() { int shmid; key_t key=SHM_KEY; // 헤더파일을 이용하여 키를 생성 char *memory_segment=NULL; // 공유 메모리의 주소를 담을 변수 char *buf; char buff[10] = "exit"; // 공유 메모리 식별자 생성 if((shmid=shmget(key, SHM_SIZE, IPC_CREAT|0666)) == -1) { printf("shmget failed\n"); exit(0); } // 생성된 메모리에 연결 if((memory_segment=shmat(shmid,NULL,0))==(void*) -1) { printf("shmat failed\n"); exit(0); } // buf변수는 공유메모리의 시작주소 + 1의 주소를 가짐 buf = memory_segment + 1; while(1) //무한루프 { // 공유 메모리의 첫번째 값인 플래그를 비교 if(memory_segment[0] == Client_WRITE_FLAG) //클라이언트 송신 플래그일 경우 { printf("My message : "); fgets(buf,1023,stdin); // 보낼 메시지를 buf에 입력 buf[strlen(buf)-1] ='\0'; // buf의 끝에 NULL을 삽입 if(strcmp(buf, buff) == 0) { // 입력받은 값이 exit일 경우 플래그값을 바꾸고 종료 strcpy(buf,"Your opponent has left..."); buf[strlen(buf)-1] = '\0'; memory_segment[0] = Client_leave_FLAG; exit(0); } memory_segment[0] = Server_READ_FLAG; // exit가 아닐 경우 플래그 변경 } else if(memory_segment[0] == Client_READ_FLAG) { // 클라이언트 수신 플래그일 경우 printf("receive message : "); puts(buf); // 공유메모리 즉 buf에 있는값을 읽음 memory_segment[0] = Client_WRITE_FLAG; // 플래그 변경 } else if(memory_segment[0] == Server_leave_FLAG) { //서버가 종료 플래그를 보내올 경우 puts(buf); exit(0); } sleep(1); } shmctl(shmid, IPC_RMID, NULL); //무한루프가 종료될 경우 공유메모리를 해제 } |
/* shm2.c */ 두번째 독립 프로세스 - Server #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include "shm.h" int main() { int shmid; key_t key = SHM_KEY; char *memory_segment=NULL; char *buf; char buff[10] = "exit"; if((shmid=shmget(key, SHM_SIZE, IPC_CREAT|0666)) == -1) { printf("shmget failed\n"); exit(0); } if((memory_segment=shmat(shmid,NULL,0))==(void*) -1) { printf("shmat failed\n"); exit(0); } buf = memory_segment + 1; memory_segment[0] = Server_WRITE_FLAG; while(1) { if(memory_segment[0] == Server_WRITE_FLAG) { printf("My message : "); fgets(buf,1023,stdin); buf[strlen(buf)-1] = '\0'; if(strcmp(buf, buff) == 0) { strcpy(buf,"Your opponent has left..."); buf[strlen(buf)-1] = '\0'; memory_segment[0] = Server_leave_FLAG; exit(0); } memory_segment[0] = Client_READ_FLAG; } else if(memory_segment[0] == Server_READ_FLAG) { printf("receive message : "); puts(buf); memory_segment[0] = Server_WRITE_FLAG; } else if(memory_segment[0] == Client_leave_FLAG) { puts(buf); exit(0); } sleep(1); } shmctl(shmid, IPC_RMID, NULL); } |
/* shm.h */ 각각의 독립 프로세스가 사용할 헤더 파일 #define MY_ID 0 #define SHM_KEY (0x9000 + MY_ID) //공통된 key값 #define SHM_SIZE 1024 // 공유 메모리 크기 #define SHM_MODE // 각각의 플래그 값 #define Server_READ_FLAG 0 #define Server_WRITE_FLAG 1 #define Client_READ_FLAG 2 #define Client_WRITE_FLAG 3 #define Server_leave_FLAG 4 #define Client_leave_FLAG 5 |
● 예제 분석
예제 소스코드는 클라이언트와 서버가 공통된 공유메모리를 사용하며, 한쪽에서 메시지를 보내면 플래그를 변경하여 다른 한쪽에서 메시지를 받고난 뒤 플래그를 변경하여 메시지를 입력하는 형식의 무한루프를 돌고 있습니다.
각각의 플래그값을 활용하여 실시간 채팅이 가능하며, 메시지로 exit를 입력하면 메시지를 비교하여 서로 종료될 수 있도록 코드를 구현하였습니다.
아래는 결과입니다.
이번 포스팅까지가 Inter-Process-Commuication 기법들에 대한 소개였고, 다음 포스팅에서는 동기화 기법 중 세마포어에 대해 알아보도록 하겠습니다.
'CS > 시스템 프로그래밍' 카테고리의 다른 글
Semaphore(System V vs POSIX) -Infinite (0) | 2022.06.21 |
---|---|
시스템 V IPC (System V) 1 -Infinite (0) | 2022.06.21 |
파이프(PIPE) -Infinite (0) | 2022.06.20 |
시그널(signal) -Infinite (0) | 2022.06.20 |
쓰레드(Thread) -Infinite (0) | 2022.06.20 |
@Beemo9 :: BeHinD
개발 기술 블로그, Dev
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!