shmget을 사용하여 C에서 공유 메모리 할당
이 기사에서는shmget
함수를 사용하여 C에서 공유 메모리를 할당하는 방법에 대해 설명합니다.
shmget
을 사용하여 C에서 공유 메모리 할당
공유 메모리는 두 개 이상의 프로세스가 데이터를 교환하고 사용자 공간에서 빠르게 통신 할 수 있도록하는 프로세스 간 통신 방법 중 하나입니다. 공유 메모리는 여러 프로세스가 메모리에서 동일한 영역을 공유하고 필요에 따라이 세그먼트를 수정/액세스 할 수 있음을 의미합니다.
다음 예제에서 보여줄 인터페이스는 System V 공유 메모리라고하며shmget
, shmat
, shmdt
및shmctl
의 네 가지 기능을 사용하여 제공됩니다.
shmget
은 새 공유 메모리 세그먼트를 생성하거나 이미 생성된 메모리 세그먼트의 식별자를 검색하는 데 사용됩니다.shmat
호출은 지정된 공유 메모리 세그먼트를 호출 프로세스의 메모리 공간에 연결하는 데 사용됩니다.shmdt
를 사용하여 주어진 메모리 세그먼트를 분리 할 수 있습니다.shmctl
은 여러 옵션으로 세그먼트를 수정하고 할당 해제하는 데 사용됩니다.
다음 예제 코드는 새로운 공유 세그먼트를 생성 한 다음 여기에 일부 텍스트를 쓰는 하나의 프로세스에 대해shmget
및shmat
함수의 기본 사용법을 구현합니다. shmget
함수는 세 개의 인수를 취하며 그 중 첫 번째는 메모리 세그먼트의 키입니다. 키 값은 새 세그먼트를 만들어야하는 경우IPC_PRIVATE
매크로가 될 수 있고 호출을 통해 메모리 식별자를 가져와야하는 경우 기존 세그먼트의 키 값이 될 수 있습니다. shmget
의 두 번째 인수는 세그먼트의 크기를 지정하고 세 번째 인수는 여러 값을 포함하기 위해 OR로 연결할 수있는 권한 플래그입니다.
메모리 세그먼트가 생성되면 세그먼트 식별자가 얻어지고shmat
함수에 전달되어 주어진 메모리를 연결할 수 있습니다. 사용자는shmat
에 대한 두 번째 인수로 주어진 메모리 세그먼트를 첨부 할 특정 주소를 전달할 수 있습니다. 그러나 일반적으로 커널이 주소를 선택하도록하고이를 나타 내기 위해NULL
을 지정하는 것이 좋습니다.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wait.h>
enum { SEGMENT_SIZE = 0x6400 };
const char *data = "Hello there!";
int main(int argc, char *argv[]) {
int status;
int segment_id;
segment_id = shmget(IPC_PRIVATE, SEGMENT_SIZE,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
char *sh_mem = (char *)shmat(segment_id, NULL, 0);
printf("Segment ID %d\n", segment_id);
printf("Attached at %p\n", sh_mem);
memmove(sh_mem, data, strlen(data) + 1);
printf("%s\n", sh_mem);
shmdt(sh_mem);
shmctl(segment_id, IPC_RMID, 0);
exit(EXIT_SUCCESS);
}
출력:
Segment ID 1540195
Attached at 0x7f6ba1437000
Hello there!
shmat
함수가 유효한 포인터를 반환하면이를 임의의 메모리 주소로 처리하고 필요에 따라 작업 할 수 있습니다. 마지막으로shmdt
및shmctl
함수가 호출되어 주어진 세그먼트를 분리하고 메모리 할당을 해제합니다. 할당 된 메모리 세그먼트에서shmctl
이 호출되지 않는다고 가정합니다. 이 경우 프로그램이 종료 된 후에도 시스템 메모리에 남아 있으며 전체 공유 메모리 세그먼트에 대한 시스템 전체 제한에 도달 할 수 있습니다.
반면에 다음 샘플 코드는 두 프로세스가 공유 메모리를 사용하여 상호 작용하는 방법을 보여줍니다. 코드는"Hello there!"
문자열을 인쇄 한 후 기본 프로세스가 분기되고 동일한 주소에 다른 문자열을 저장하는 자식이 생성된다는 점을 제외하면 앞의 예와 동일합니다. 한편, 부모 프로세스는 일시 중단되고 자식이 종료 될 때까지 기다린 다음 성공 코드로 종료됩니다. 새로 저장된 문자열이 콘솔에 인쇄됩니다. 여러 프로세스가 공유 메모리 세그먼트를 동시에 수정하고 액세스해야하는 경우 프로그래머는 세마포와 같은 일부 동기화 도구를 사용해야합니다.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wait.h>
enum { SEGMENT_SIZE = 0x6400 };
const char *data = "Hello there!";
int main(int argc, char *argv[]) {
int status;
int segment_id;
segment_id = shmget(IPC_PRIVATE, SEGMENT_SIZE,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
char *sh_mem = (char *)shmat(segment_id, 0, 0);
printf("Segment ID %d\n", segment_id);
printf("Attached at %p\n", sh_mem);
memmove(sh_mem, data, strlen(data) + 1);
printf("%s\n", sh_mem);
pid_t child_pid = fork();
if (child_pid == -1) perror("fork");
if (child_pid == 0) {
strcpy(sh_mem, "NEW DATA Stored by Child Process\0");
printf("child pid - %d\n", getpid());
exit(EXIT_SUCCESS);
} else {
pid_t ret = waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
if (ret == -1) perror("waitpid");
if (WIFEXITED(status))
printf("Child exited, status - %d\n", WEXITSTATUS(status));
if (WEXITSTATUS(status) == 0) printf("%s\n", sh_mem);
}
shmdt(sh_mem);
shmctl(segment_id, IPC_RMID, 0);
exit(EXIT_SUCCESS);
}
출력:
Segment ID 1540195
Attached at 0x7fd825a25000
Hello there!
child pid - 27291
Child exited, status - 0
NEW DATA Stored by Child Process
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook