본문 바로가기
✒️ Linux Programming/with Oracle Virtual Box & Ubuntu

[Linux & Ubuntu] C 프로그래밍을 통한 공유 메모리 & 메시지 큐 사용 프로세스 구현 #2

by A Lim Han 2023. 10. 9.

🌷 C 프로그래밍을 통한 공유 메모리 & 메시지 큐 사용 프로세스 구현 # 2

# 구현할 프로그램 개요

프로그램 번호 프로그램 1 프로그램 2 프로그램 3
수행 작업 1초 간격으로 1~10까지
값을 공유 메모리에
차례로 입력
루프를 돌며 공유 메모리
값을 읽어와
메시지 큐에 입력
루프를 돌며 대기 후
메시지 큐에 입력된 값
짝수만을 읽어와 출력

 


💮 C 언어를 통한 프로그램 # 2 구현

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>

#define SHM_KEY 1234
#define MSG_KEY 5678

// 공유 메모리 구조체 정의
struct SharedMemory {
ㅤㅤint value;
};

// 메시지 큐 구조체 정의
struct Message {
ㅤㅤlong mtype;
ㅤㅤint data;
};

int main() {
ㅤㅤ// 공유 메모리 연결
ㅤㅤint shmid = shmget(SHM_KEY, sizeof(struct SharedMemory), 0666);
ㅤㅤif (shmid == -1) {
ㅤㅤㅤㅤperror("shmget");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}
ㅤㅤstruct SharedMemory *shm = (struct SharedMemory *)shmat(shmid, NULL, 0);
ㅤㅤif (shm == (struct SharedMemory *)(-1)) {
ㅤㅤㅤㅤperror("shmat");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}

ㅤㅤ// 메시지 큐 생성
ㅤㅤint msqid = msgget(MSG_KEY, 0666 | IPC_CREAT);
ㅤㅤif (msqid == -1) {
ㅤㅤㅤㅤperror("msgget");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}

ㅤㅤprintf("Program 2 is running...\n");

ㅤㅤstruct Message message;
ㅤㅤwhile (1) {
ㅤㅤㅤㅤif (shm->value != 0) {
ㅤㅤㅤㅤㅤㅤmessage.mtype = 1;  // 메시지 타입 1
ㅤㅤㅤㅤㅤㅤmessage.data = shm->value;
ㅤㅤㅤㅤㅤㅤmsgsnd(msqid, &message, sizeof(int), 0);
ㅤㅤㅤㅤㅤㅤprintf("Program 2 sent to message queue: %d\n", message.data);
ㅤㅤㅤㅤㅤㅤshm->value = 0;  // 공유 메모리 초기화
ㅤㅤㅤㅤ}
ㅤㅤ}

ㅤㅤ// 공유 메모리 및 메시지 큐 삭제하지 않음

ㅤㅤreturn 0;
}

 


1.  프로그램 실행에 필요한 라이브러리 include

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>

 

++ 각 Include 문 상세 설명

include 문 역할
stdio.h 표준 입출력 함수를 포함하는 헤더 파일
stdlib.h C 프로그래밍 언어에서 기본적인
유틸리티 함수들을 포함하는 헤더 파일
unistd.h 유닉스 및 리눅스 시스템에서 제공하는
시스템 호출을 포함하는 헤더 파일
sys/types.h 시스템 데이터 형식을 정의하는 헤더 파일
sys/ipc.h IPC(Inter-Process Communication) 기능을
사용하기 위해 필요한 헤더 파일
sys/shm.h 공유 메모리 세그먼트 제어 시
사용되는 헤더 파일
sys/msg.h 시스템 V IPC 메시지 큐를 다루기 위한 헤더 파일

2.  공유 메모리를 식별하는 데 사용될 키 정의

#define SHM_KEY 1234
#define MSG_KEY 5678

3.  공유 메모리에 저장될 데이터 구조 정의

struct SharedMemory {
ㅤㅤint value;
};

4.  메시지 큐 구조체 정의

// 메시지 큐 구조체 정의
struct Message {
ㅤㅤlong mtype;
ㅤㅤint data;
};

 

++  구조체 필드 설명

mtype data
메시지 큐에서 메시지를 수신할 때 메시지의 유형 지정 메시지에 관련된 정수형 데이터 저장

5.  main() 함수에서 공유 메모리 연결

int main() {
ㅤㅤ// 공유 메모리 연결
ㅤㅤint shmid = shmget(SHM_KEY, sizeof(struct SharedMemory), 0666);
ㅤㅤif (shmid == -1) {
ㅤㅤㅤㅤperror("shmget");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}

 

++  코드 설명 상세

코드 설명
shmget() 공유 메모리 세그먼트 생성 & 참조하기 위한 함수
SHM_KEY 공유 메모리 세그먼트 식별
sizeof(struct SharedMemory) 필요한 메모리 크기 정의
0666 퍼미션 설정용 매개변수
shmid == -1 shmget() 의 작업 실패 시 -1 반환
perror() 오류 메시지 출력용 함수
exit(1) exit() 을 호출하여 프로그램 종료

6.  공유 메모리를 현재 프로세스의 주소 공간에 첨부

struct SharedMemory *shm = (struct SharedMemory *)shmat(shmid, NULL, 0);
ㅤㅤif (shm == (struct SharedMemory *)(-1)) {
ㅤㅤㅤㅤperror("shmat");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}

 

+  코드 설명 상세

코드 설명
shmat(shmid, NULL, 0) 공유 메모리 세그먼트를 프로세스의 주소 공간에 첨부
shm == (struct SharedMemory *)(-1) shmget() 의 작업 실패 시 -1 반환
perror("shmat") 오류 메시지 출력용 함수
exit(1) exit() 을 호출하여 프로그램 종료

 

 

++  인자값 설명 상세

인자 설명
shmid 공유 메모리 식별자
NULL 메모리 세그먼트 주소 자동 선택
0 첨부 수행하는 플래그 매개변수

7.  메시지 큐 생성

// 메시지 큐 생성
ㅤㅤint msqid = msgget(MSG_KEY, 0666 | IPC_CREAT);
ㅤㅤif (msqid == -1) {
ㅤㅤㅤㅤperror("msgget");
ㅤㅤㅤㅤexit(1);
ㅤㅤ}

 

++ 코드 설명 상세

코드 설명
int msqid = msgget() 메시지 큐 식별자를 얻기 위해 사용되는 함수
MSG_KEY 메시지 큐 식별
0666 | IPC_CREAT 권한 지정 + 메시지 큐가 없는 경우
새로 생성하도록 하는 플래그

8.  공유 메모리 검사 후 메시지 큐에 값 전송

printf("Program 2 is running...\n");

ㅤㅤstruct Message message;
ㅤㅤwhile (1) {
ㅤㅤㅤㅤif (shm->value != 0) {
ㅤㅤㅤㅤㅤㅤmessage.mtype = 1;  // 메시지 타입 1
ㅤㅤㅤㅤㅤㅤmessage.data = shm->value;
ㅤㅤㅤㅤㅤㅤmsgsnd(msqid, &message, sizeof(int), 0);
ㅤㅤㅤㅤㅤㅤprintf("Program 2 sent to message queue: %d\n", message.data);
ㅤㅤㅤㅤㅤㅤshm->value = 0;  // 공유 메모리 초기화
ㅤㅤㅤㅤ}
ㅤㅤ}

 

++ 코드 설명 상세

코드 설명
struct Message message Message 구조체를 인스턴스화하여 새 메시지 생성
message.mtype 1 메시지의 유형을 1로 설정
(공유 메모리의 값이 0이 아닐 경우)
message.data = shm->value 메시지의 데이터를 공유 메모리의 값으로 설정
msgsnd() 메시지 큐에 메시지 전송
sizeof(int) 전송할 데이터의 크기를 나타내는 매개변수
shm->value = 0 공유 메모리의 값을 0으로 초기화

9.  프로그램 종료 후 공유 메모리 & 메시지 큐를 보존한 상태로 리턴

ㅤㅤ// 공유 메모리 및 메시지 큐 삭제하지 않음

ㅤㅤreturn 0;
}