Voici un exemple de mémoire partagée :
#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;
}
Étapes :
-
Utilisez ftok pour convertir un nom de chemin et un identifiant de projet en une clé System V IPC
-
Utilisez shmget qui alloue un segment de mémoire partagée
-
Utilisez shmat pour attacher le segment de mémoire partagée identifié par shmid à l'espace d'adressage du processus appelant
-
Faire les opérations sur la zone mémoire
-
Détacher en utilisant shmdt
Il existe deux approches :shmget
et mmap
. Je vais parler de mmap
, car il est plus moderne et flexible, mais vous pouvez jeter un œil à man shmget
(ou ce tutoriel) si vous préférez utiliser les outils à l'ancienne.
Le mmap()
La fonction peut être utilisée pour allouer des tampons de mémoire avec des paramètres hautement personnalisables pour contrôler l'accès et les autorisations, et pour les sauvegarder avec un stockage de système de fichiers si nécessaire.
La fonction suivante crée un tampon en mémoire qu'un processus peut partager avec ses enfants :
#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);
}
Voici un exemple de programme qui utilise la fonction définie ci-dessus pour allouer un tampon. Le processus parent écrira un message, fork, puis attendra que son enfant modifie le tampon. Les deux processus peuvent lire et écrire dans la mémoire partagée.
#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);
}
}