Hier ist ein Beispiel für Shared Memory :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024 /* make it a 1K shared memory segment */
int main(int argc, char *argv[])
{
key_t key;
int shmid;
char *data;
int mode;
if (argc > 2) {
fprintf(stderr, "usage: shmdemo [data_to_write]\n");
exit(1);
}
/* make the key: */
if ((key = ftok("hello.txt", 'R')) == -1) /*Here the file must exist */
{
perror("ftok");
exit(1);
}
/* create the segment: */
if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
/* attach to the segment to get a pointer to it: */
if ((data = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
exit(1);
}
/* read or modify the segment, based on the command line: */
if (argc == 2) {
printf("writing to segment: \"%s\"\n", argv[1]);
strncpy(data, argv[1], SHM_SIZE);
} else
printf("segment contains: \"%s\"\n", data);
/* detach from the segment: */
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
return 0;
}
Schritte :
-
Verwenden Sie ftok, um einen Pfadnamen und eine Projektkennung in einen System-V-IPC-Schlüssel umzuwandeln
-
Verwenden Sie shmget, das ein gemeinsames Speichersegment zuweist
-
Verwenden Sie shmat, um das von shmid identifizierte Shared-Memory-Segment an den Adressraum des aufrufenden Prozesses anzuhängen
-
Führen Sie die Operationen im Speicherbereich aus
-
Trennen mit shmdt
Es gibt zwei Ansätze:shmget
und mmap
. Ich werde über mmap
sprechen , da es moderner und flexibler ist, aber Sie können einen Blick auf man shmget
werfen (oder dieses Tutorial), wenn Sie lieber die Tools im alten Stil verwenden möchten.
Die mmap()
-Funktion kann verwendet werden, um Speicherpuffer mit hochgradig anpassbaren Parametern zuzuweisen, um Zugriff und Berechtigungen zu steuern und sie bei Bedarf mit Dateisystemspeicher zu sichern.
Die folgende Funktion erstellt einen In-Memory-Puffer, den ein Prozess mit seinen Kindern teilen kann:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
void* create_shared_memory(size_t size) {
// Our memory buffer will be readable and writable:
int protection = PROT_READ | PROT_WRITE;
// The buffer will be shared (meaning other processes can access it), but
// anonymous (meaning third-party processes cannot obtain an address for it),
// so only this process and its children will be able to use it:
int visibility = MAP_SHARED | MAP_ANONYMOUS;
// The remaining parameters to `mmap()` are not important for this use case,
// but the manpage for `mmap` explains their purpose.
return mmap(NULL, size, protection, visibility, -1, 0);
}
Das Folgende ist ein Beispielprogramm, das die oben definierte Funktion verwendet, um einen Puffer zuzuweisen. Der übergeordnete Prozess schreibt eine Nachricht, verzweigt sich und wartet dann darauf, dass sein untergeordneter Prozess den Puffer ändert. Beide Prozesse können den Shared Memory lesen und schreiben.
#include <string.h>
#include <unistd.h>
int main() {
char parent_message[] = "hello"; // parent process will write this message
char child_message[] = "goodbye"; // child process will then write this one
void* shmem = create_shared_memory(128);
memcpy(shmem, parent_message, sizeof(parent_message));
int pid = fork();
if (pid == 0) {
printf("Child read: %s\n", shmem);
memcpy(shmem, child_message, sizeof(child_message));
printf("Child wrote: %s\n", shmem);
} else {
printf("Parent read: %s\n", shmem);
sleep(1);
printf("After 1s, parent read: %s\n", shmem);
}
}