0. 시작하기전에
- 이전 포스팅에서 IPC기법 중 pipe와 message queue 기법을 직접 구현해 보았다.
- 이번 포스팅에서는 다른 종류의 IPC기법을 실습해 볼 예정이다.
1. ipcs 명령어
- ipcs 명령어는 현재 커널공간에 생성되어 있는 message queue, 공유메모리, 세마포어를 확인할 수 있다.
- 아래의 사진처럼, 현재 커널 공간을 활용하고 있는 메모리를 보여준다.
a) 메세지 큐를 송수신 해보자.
- 우선, 이전 포스팅에서 만들어 놓은 메세지 큐 송수신 프로그램을 실행시켜보자.
- 위의 사진은 Message queue를 전송한 후 ipcs명령어를 입력한 것이다.
- message queue가 50bytes의 크기로, 1개의 메세지를 담고 있다는 것을 보여준다.
- 그렇다면 메세지를 수신하고 나면 커널영역의 해당 메모리는 사라질까?
- 위의 사진처럼, 해당 메모리는 사라지지 않는다.
- 다만, 크기와 메세지 수가 0으로 변한 것을 알 수 있다.
- 메세지를 수신받았다고, message queue를 사용하지 않겠다는 의미가 아니다.
- message queue를 다시 사용할 수 있기 때문에, 메모리 상에서는 남아있게 된다.
- 만약 메세지 큐를 삭제하고 싶다면, msgctl() 함수를 이용해 제거할 수 있다는 것을 참고하자.
2. shared memory(공유 메모리)
- 공유 메모리 기법은 커널 영역의 메모리에 변수를 할당하여, 공유 변수처럼 사용하는 방식이다.
- 변수를 생성하여 값을 바꾸는 방식으로, 변수를 이용해 소통을 한다.
- message queue와 마찬가지로, 공유 메모리는 고유의 key를 갖고 있으며
- 고유 key 값을 통해 여러 프로세스의 접근이 가능하도록 설계되어있다.
a) 공유 메모리 및 key 생성
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
// key: 임의 숫자 또는 ftok 함수를 통해 생성된 키 값
// size: 공유 메모리 크기
// shmflg: 공유 메모리 속성 및 권한
// 리턴 값: 공유 메모리 식별자를 반환
int shmget(key_t key, size_t size, int shmflg);
// 예시
shmid = shmget((key_t)1234, SIZE, IPC_CREAT|0666));
b) 공유 메모리와 변수 Mapping
- 커널영역에 공유 메모리 영역을 할당하면서 동시에 key를 생성하였다.
- 이제 이 공유메모리를 프로세스의 어떤 변수에 mapping(연결)을 시켜야 한다.
#include <sys/types.h>
#include <sys/shm.h>
// shmid: shmget 함수로 생성한 공유 메모리 식별자
// shmaddr: 공유 메모리 연결 주소 (보통 (char*)NULL로 설정하면, 알아서 적절한 주소로 연결)
// shmflg: 공유 메모리의 읽기/쓰기 권한(0이면 읽기/쓰기 가능, SHM_RDONLY면 읽기만 가능)
// 리턴 값: 성공시 연결된 공유 메모리의 시작 주소를 반환
void *shmat(int shmid, cont void *shmaddr, int shmflg);
// 예시
shmaddr = (char *)shmat(shmid, (char *)NULL, 0);
* shmat = shared memory attach
* shmaddr = shared memory address
c) 공유 메모리 해제
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(char *shmaddr);
* shmdt = shared memory detach
d) 공유 메모리 읽기
- 포인터 변수처럼 사용하면 된다.
printf("%s\n", (char *)shmaddr);
e) 공유 메모리에 쓰기
strcpy((char *)shmaddr, "Linux Programming");
f) 공유 메모리 영역을 삭제하는 방법
- message queue에서 msgctl()을 사용하여 message queue 메모리를 삭제하는 것처럼,
- 공유 메모리도 shmctl()을 사용하여 삭제할 수 있다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
// shmid: shmget 함수로 생성한 공유 메모리 식별자
// cmd: 수행할 제어 기능 (예: IPC_RMID - shmid로 지정한 공유 메모리 제거)
// buf: 제어 기능에 사용되는 공유 메모리 구조체의 구조
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
// 예시
shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL);
* shctl = shared memory control
3. Share Memory 실습 예제
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int shmid, pid;
char *shmaddr_parent, *shmaddr_child; // 공유 메모리 영역을 할당할 포인터 변수
shmid = shmget((key_t)1234, 10, IPC_CREAT|0664); // 키값 생성
if(shmid == -1) {
perror("shmget error\n");
exit(1);
}
pid = fork(); // 자식 프로세스 생성
if(pid > 0) { // 2.부모 프로세스
wait(0); // 자식 프로세스의 exit() 호출까지 대기
shmaddr_parent = (char *)shmat(shmid, (char *)NULL, 0);
printf("%s\n", shmaddr_parent); // 공유 메모리 값을 읽음(read)
shmdt((char *)shmaddr_parent);
}
else { // 1.자식 프로세스
shmaddr_child = (char *)shmat(shmid, (char *)NULL, 0); // 공유 메모리 키를 변수에 매핑
strcpy((char *)shmaddr_child, "Hello Parent!"); // 공유 메모리에 쓰기(write)
shmdt((char *)shmaddr_child); // 포인터 변수를 공유 메모리에서 해제
exit(0);
}
shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); // 공유메모리를 커널영역에서 삭제
return 0;
}
'컴퓨터공학기초 개념 > 시스템 프로그래밍' 카테고리의 다른 글
29. 쉘 스크립트 - 이해와 변수 (0) | 2021.09.23 |
---|---|
28. 시그널 - 사용법 이해 (0) | 2021.09.21 |
26. 프로세스 - IPC 기법(pipe, message queue) (0) | 2021.09.17 |
25. 프로세스 - 우선순위 스케줄링 시스템 콜 (0) | 2021.09.17 |
24. 프로세스 - 프로세스 생성과 종료 총정리 (0) | 2021.09.17 |
댓글