시스템 소프트웨어
공유 메모리 (Shared Memory)
masimelo
2023. 3. 11. 22:24
공유메모리
공유메모리
- 공유메모리 = 프로세스 간 통신을 위한 메커니즘
- 기본적으로 프로세스는 다른 프로세스의 메모리 영역에 접근이 불가능함
- 가끔은 여러 개의 프로세스가 특정 메모리 영역을 동시에 접근해야 할 필요성을 가질 때가 있음
- 여러 개의 프로세스가 동일한 메모리 영역에 접근할 수 있도록 제공함
- 서로 다른 프로세스가 특정한 논리 메모리 영역에 접근하여 데이터를 읽고 쓸 수 있음
- 여러 ipc 중에서 가장 빠른 수행 속도를 보여줌
- 하나의 메모리 영역을 공유해서 접근하게 되므로, 데이터 복사와 같은 불필요한 오버헤드가 발생하지 않기 때문
- 동기화 기능을 제공하지 않기 때문에 세마포어 등의 메커니즘을 사용하여 메모리 영역의 접근을 동기화해야 함
공유 메모리 함수
ftok()
#include < sys/ipc,h>
#include <sys/types.h>
key_t ftok(const char * pathname, int proj_id);
- 설명
- System V IPC에서 사용할 키를 생성 함
- 인자
- pathname : 키를 생성할 경로 또는 이름
- proj_id : 같은 경로의 키에 대해서 구분하기 위한 값
- 반환
- 성공하면 키값
- 실패하면 -1
shmget()
#include <sys/shm.h>
#include <sys/types.h>
int shmget(key_t key, size_t size, int shmflag);
- 설명
- 공유 메모리를 생성하고 접근할 수 있는 식별자를 반환함
- 인자
- key : 공유 메모리를 식별하는 키 값
- size : 생성하고자 하는 고유 메모리의 크기
- shmflag : 공유 메모리의 생성에 관한 플래그
- 반환
- 성공하면 공유 메모리 식별자
- 실패하면 -1
shmat()
#include <sys/shm.h>
#include <sys/types.h>
void *shmat(int shmid, const void * shmaddr, int shmflag);
- 설명
- 프로세스가 공유메모리를 사용할 수 있도록 연결함
- 인자
- shmid : 공유 메모리의 식별자
- shmaddr : 공유 메모리가 연결될 영역의 주소 ( 대부분 커널에서 설정하도록 NULL을 사용)
- shmflag : 공유 메모리 영역의 읽기/쓰기에 관한 플래그
- 0
- 공유 메모리에 데이터를 읽고 쓸 수 있음
- SHM_RDONLY
- 공유 메모리를 읽기 전용으로 연결함
- 0
- 반환
- 성공하면, 공유 메모리 영역의 시작 주소
- 실패하면 -1
shmdt()
#include <sys/shm.h>
int shmdt(const void * shmaddr);
- 설명
- 공유 메모리를 현재 프로세스로부터 분리함
- 인자
- shmaddr : 공유 메모리 영역의 시작 주소
- 반환
- 성공하면 0
- 실패하면 -1
strucrt shmid_ds
#include <sys/shm.h>
#include <sys/types.h>
struct shmid_ds
{
struct ipc_perm shm_perm; // 퍼미션
int shm_segsz; // 메모리 공간의 크기
time_t shm_dtime; // 마지막 attach 시간
time_t shm_dtime; // 마지막 detach 시간
time_t shm_ctime; // 마지막 변경 시간
unsigned short shm_cpid; // 생성프로세스의 pid
unsigned short shm_lpid; // 마지막으로 작동한 프로세스의 pid
short shm_nattch; // 현재 접근한 프로세스의 수
};
shmctl()
#include <sys/mhm.h>
int shmctl(int shmid, int cmd, shruct shmid_ds * buf);
- 설명
- 공유메모리를 제어함
- 인자
- shmid : 공유 메모리의 식별자
- cmd : 제어동작에 관한 플래그
- IPC_RMID : 지정한 공유 메모리를 제거함
- IPC_SET : 공유메모리의 정보를 지정한 정보로 변경함
- IPC_STAT : 공유 메모리의 정보를 지정한 메모리 공간에 저장함
- buf : 제어에 사용되는 공유 메모리 구조체의 메모리 공간에 대한 포인터
- 반환
- 성공하면 0
- 실패하면 -1
- 예시
- 서버
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_SHM_SIZE 512
void signalHandler(int signum);
void myfunc(void);
key_t mykey=0;
int shmid =0;
int *shmaddr = NULL;
int main(int argc, char const *argv[]){
mykey = ftok("Myshmkey",2);
shmid = shmget(mykey, MAX_SHM_SIZE, IPC_CREAT|0600);
shmaddr = shmat(shmid, NULL, 0);
signal(SIGINT, signalHandler);
signal(SIGUSR1,signalHandler);
while(1){
puts("Wait...");
pause();
}
return 0;
}
void signalHandler(int signum){
struct shmid_ds buf;
if(signum == SIGINT){
shmdt(shmaddr);
shmctl(shmid,IPC_RMID, NULL);
exit(0);
}
else if(signum == SIGUSR1){
myfunc();
}
}
void myfunc(void){
struct shmid_ds buf;
int data=0;
memcpy(&data, shmaddr,sizeof(int));
printf("Receive : %d\\n",data);
data +=1;
memcpy(shmaddr, &data, sizeof(int));
printf("Send : %d \\n",data);
shmctl(shmid, IPC_STAT,&buf);
kill(buf.shm_lpid,SIGUSR1);
}
- 클라이언트
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_SHM_SIZE 512
void signalHandler(int signum);
void myfunc(void);
key_t mykey =0;
int shmid=0;
int *shmaddr = NULL;
int main(int argc, char const * argv[]){
struct shmid_ds buf;
int data = 0;
mykey = ftok("Myshmkey",2);
shmid=shmget(mykey, MAX_SHM_SIZE, IPC_CREAT);
shmaddr = shmat(shmid, NULL,0);
signal(SIGUSR1, signalHandler);
while(1){
printf("<< ");
scanf("%d", &data);
fflush(stdout);
fflush(stdin);
memcpy(shmaddr, &data, sizeof(int));
shmctl(shmid, IPC_STAT,&buf);
kill(buf.shm_cpid,SIGUSR1);
pause();
}
return 0;
}
void signalHandler(int signum){
int data=0;
if(signum == SIGUSR1){
memcpy(&data, shmaddr,sizeof(int));
printf(">> %d\\n",data);
}
}