POSIX Shared Memory

Ce forum est dédié à apprendre le développement de programmes user mode sur Linux

Moderator: Rick

Post Reply
Hydraxx
Site Admin
Posts: 114
Joined: Mon Jan 12, 2026 4:04 pm
Location: France
Contact:

POSIX Shared Memory

Post by Hydraxx »

POSIX Shared Memory

1. Introduction

La mémoire partagée POSIX permet à plusieurs processus d'accéder à une même région mémoire.

Elle constitue l'un des mécanismes IPC les plus rapides, car les processus n'ont pas besoin de copier les données à travers un pipe ou une file de messages à chaque échange.

Le principe général est :
  • créer ou ouvrir un objet de mémoire partagée avec shm_open() ;
  • définir sa taille avec ftruncate() ;
  • mapper l'objet dans l'espace d'adressage du processus avec mmap() ;
  • lire ou écrire directement dans la zone mémoire ;
  • supprimer le nom de l'objet avec shm_unlink() lorsqu'il n'est plus nécessaire.
Contrairement à System V, la mémoire partagée POSIX utilise un modèle très proche de celui des fichiers et de mmap().


2. Vue d'ensemble

Un objet de mémoire partagée POSIX est un objet noyau identifié par un nom.

Exemple :

Code: Select all

"/inside_shm"
Lorsqu'un processus appelle :

Code: Select all

shm_open()
le système retourne un descripteur de fichier.

Ce descripteur peut ensuite être utilisé avec :

Code: Select all

ftruncate()
mmap()
fstat()
close()
Le mapping est généralement réalisé avec :

Code: Select all

MAP_SHARED
afin que les modifications soient visibles par les autres processus.


3. Étapes générales

Le schéma classique est :
  • 1. Créer ou ouvrir l'objet avec shm_open().
  • 2. Définir sa taille avec ftruncate().
  • 3. Mapper l'objet avec mmap().
  • 4. Utiliser la zone mémoire.
  • 5. Retirer le mapping avec munmap().
  • 6. Fermer le descripteur avec close().
  • 7. Supprimer le nom avec shm_unlink().

4. Création d'un objet de mémoire partagée

shm_open()

Prototype :

Code: Select all

int shm_open(
    const char *name,
    int oflag,
    mode_t mode
);
Exemple :

Code: Select all

int fd = shm_open(
    "/inside_shm",
    O_CREAT | O_RDWR,
    0666
);
En cas de succès, shm_open() retourne un descripteur de fichier.

En cas d'erreur :

Code: Select all

-1

5. Nom d'un objet POSIX

Le nom permet à plusieurs processus d'ouvrir le même objet.

Exemple :

Code: Select all

"/inside_shm"
Sous Linux, le nom commence normalement par :

Code: Select all

/
Deux processus peuvent donc faire :

Code: Select all

shm_open("/inside_shm", ...);
et référencer le même objet noyau.


6. Flags de shm_open()

Les flags importants sont :
  • O_RDONLY ;
  • O_RDWR ;
  • O_CREAT ;
  • O_EXCL ;
  • O_TRUNC.

O_RDONLY

Ouvre l'objet en lecture seule.

Exemple :

Code: Select all

shm_open("/inside_shm", O_RDONLY, 0);

O_RDWR

Ouvre l'objet en lecture et en écriture.

Exemple :

Code: Select all

shm_open("/inside_shm", O_RDWR, 0);

O_CREAT

Crée l'objet s'il n'existe pas.

Exemple :

Code: Select all

shm_open(
    "/inside_shm",
    O_CREAT | O_RDWR,
    0666
);

O_EXCL

Utilisé avec O_CREAT.

Si l'objet existe déjà, l'appel échoue.

Exemple :

Code: Select all

shm_open(
    "/inside_shm",
    O_CREAT | O_EXCL | O_RDWR,
    0666
);

O_TRUNC

Permet de tronquer un objet existant.

Selon l'implémentation et les droits d'accès, l'objet peut être ramené à une taille nulle.


7. Permissions

Lors de la création, le paramètre mode définit les permissions.

Exemple :

Code: Select all

0666
Comme pour les fichiers Unix, les permissions sont affectées par le umask du processus.


8. Taille initiale de l'objet

Un nouvel objet créé par shm_open() possède initialement une taille nulle.

Il faut donc généralement l'agrandir avant de le mapper.

La fonction utilisée est :

Code: Select all

ftruncate()

9. ftruncate()

Prototype conceptuel :

Code: Select all

int ftruncate(
    int fd,
    off_t length
);
Exemple :

Code: Select all

if (ftruncate(fd, 4096) == -1) {
    perror("ftruncate");
}
L'objet possède maintenant une taille de :

Code: Select all

4096
octets.


10. Pourquoi définir la taille avant mmap()

Le mapping doit référencer une zone réellement présente dans l'objet.

Si l'objet a une taille nulle et que le programme tente d'accéder à une zone qui n'existe pas, le comportement n'est pas valide.

Le schéma correct est donc :

Code: Select all

shm_open()
ftruncate()
mmap()

11. Mapping de la mémoire partagée

Une fois l'objet créé et dimensionné, il peut être mappé avec :

Code: Select all

mmap()
Exemple :

Code: Select all

void *addr = mmap(
    NULL,
    4096,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    fd,
    0
);

12. MAP_SHARED

Le flag :

Code: Select all

MAP_SHARED
est essentiel.

Il indique que les modifications effectuées dans le mapping doivent être visibles par les autres processus mappant le même objet.

Exemple :

Processus A écrit :

Code: Select all

strcpy(addr, "Inside The System");
Processus B ayant mappé le même objet peut ensuite lire :

Code: Select all

"Inside The System"

13. MAP_PRIVATE ne convient pas au partage

Avec :

Code: Select all

MAP_PRIVATE
les modifications ne sont pas propagées de la même manière aux autres utilisateurs de l'objet.

Le mapping utilise un comportement privé basé notamment sur le copy-on-write.

Pour une mémoire réellement partagée entre processus, on utilise donc généralement :

Code: Select all

MAP_SHARED

14. Protections mémoire

Les protections sont choisies avec le paramètre prot de mmap().

Exemples :

Code: Select all

PROT_READ
Lecture autorisée.

Code: Select all

PROT_WRITE
Écriture autorisée.

Combinaison fréquente :

Code: Select all

PROT_READ | PROT_WRITE

15. Accès aux données

Une fois mmap() réussi, la zone peut être manipulée comme une zone mémoire classique.

Exemple :

Code: Select all

char *buffer = addr;

strcpy(buffer, "Inside The System");
Ou :

Code: Select all

struct SharedData *data = addr;

data->counter++;

16. Le descripteur peut être fermé après mmap()

Une fois le mapping créé avec succès, il n'est généralement plus nécessaire de conserver le descripteur de fichier uniquement pour maintenir le mapping.

On peut donc faire :

Code: Select all

void *addr = mmap(
    NULL,
    size,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    fd,
    0
);

close(fd);
Le mapping reste valide après close().

Le descripteur et le mapping sont deux références différentes.


17. Récupérer la taille d'un objet existant

Lorsqu'un processus ouvre un objet déjà existant, il peut récupérer sa taille avec :

Code: Select all

fstat()
Exemple :

Code: Select all

struct stat sb;

if (fstat(fd, &sb) == -1) {
    perror("fstat");
}

printf("Taille : %ld\n", (long)sb.st_size);
Cette taille peut ensuite être utilisée pour mmap().


18. Exemple d'écriture

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main(void)
{
    const char *name = "/inside_shm";
    const size_t size = 4096;

    int fd = shm_open(
        name,
        O_CREAT | O_RDWR,
        0666
    );

    if (fd == -1) {
        perror("shm_open");
        return EXIT_FAILURE;
    }

    if (ftruncate(fd, size) == -1) {
        perror("ftruncate");
        close(fd);
        return EXIT_FAILURE;
    }

    char *addr = mmap(
        NULL,
        size,
        PROT_READ | PROT_WRITE,
        MAP_SHARED,
        fd,
        0
    );

    if (addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return EXIT_FAILURE;
    }

    close(fd);

    strcpy(addr, "Inside The System");

    munmap(addr, size);

    return EXIT_SUCCESS;
}

19. Exemple de lecture

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(void)
{
    const char *name = "/inside_shm";

    int fd = shm_open(
        name,
        O_RDONLY,
        0
    );

    if (fd == -1) {
        perror("shm_open");
        return EXIT_FAILURE;
    }

    struct stat sb;

    if (fstat(fd, &sb) == -1) {
        perror("fstat");
        close(fd);
        return EXIT_FAILURE;
    }

    char *addr = mmap(
        NULL,
        sb.st_size,
        PROT_READ,
        MAP_SHARED,
        fd,
        0
    );

    if (addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return EXIT_FAILURE;
    }

    close(fd);

    printf("Message : %s\n", addr);

    munmap(addr, sb.st_size);

    return EXIT_SUCCESS;
}

20. Démapper la mémoire

Une région créée avec mmap() doit être retirée avec :

Code: Select all

munmap()
Prototype :

Code: Select all

int munmap(
    void *addr,
    size_t length
);
Exemple :

Code: Select all

munmap(addr, 4096);
Après munmap(), l'adresse n'est plus valide.


21. Suppression de l'objet

shm_unlink()

Prototype :

Code: Select all

int shm_unlink(
    const char *name
);
Exemple :

Code: Select all

shm_unlink("/inside_shm");
Cette fonction supprime le nom de l'objet de mémoire partagée.


22. shm_unlink() ne détruit pas forcément immédiatement

Si un processus possède encore :
  • un descripteur ouvert ;
  • ou un mapping actif ;
l'objet peut continuer d'exister jusqu'à la disparition des dernières références.

Cela ressemble au comportement de :

Code: Select all

unlink()
sur un fichier Unix.


23. Différence entre close(), munmap() et shm_unlink()

close()

Ferme le descripteur.

Code: Select all

close(fd);

munmap()

Supprime un mapping dans l'espace virtuel du processus.

Code: Select all

munmap(addr, size);

shm_unlink()

Supprime le nom de l'objet POSIX.

Code: Select all

shm_unlink("/inside_shm");
Ces trois opérations ont donc des rôles différents.


24. Partage entre plusieurs processus

Processus A :

Code: Select all

fd = shm_open("/inside_shm", O_CREAT | O_RDWR, 0666);
ftruncate(fd, 4096);
addrA = mmap(NULL, 4096,
             PROT_READ | PROT_WRITE,
             MAP_SHARED,
             fd,
             0);
Processus B :

Code: Select all

fd = shm_open("/inside_shm", O_RDWR, 0);
addrB = mmap(NULL, 4096,
             PROT_READ | PROT_WRITE,
             MAP_SHARED,
             fd,
             0);
addrA et addrB peuvent avoir des adresses virtuelles différentes.

Cependant, ils référencent les mêmes données partagées.


25. Les adresses virtuelles peuvent être différentes

Il n'est pas nécessaire que les deux processus obtiennent la même adresse virtuelle.

Exemple :

Code: Select all

Processus A :
0x7f1000000000

Processus B :
0x7f9000000000
Ces adresses peuvent malgré tout correspondre aux mêmes pages partagées.

Il ne faut donc généralement pas stocker de pointeurs absolus dans une structure partagée si plusieurs processus doivent les utiliser.


26. Éviter les pointeurs absolus dans la mémoire partagée

Exemple problématique :

Code: Select all

struct Shared {
    char *buffer;
};
Le pointeur :

Code: Select all

buffer
peut être valide dans le processus A mais invalide dans le processus B.

Il est souvent préférable d'utiliser :
  • des offsets ;
  • des indices ;
  • des structures entièrement contenues dans la zone partagée.
Exemple :

Code: Select all

struct Shared {
    size_t buffer_offset;
};

27. Synchronisation nécessaire

La mémoire partagée permet à plusieurs processus d'accéder aux mêmes données.

Elle ne protège cependant pas automatiquement contre les accès concurrents.

Exemple :

Code: Select all

counter++;
n'est pas forcément atomique.

Si plusieurs processus modifient simultanément counter, une race condition peut se produire.

Il faut donc utiliser un mécanisme de synchronisation.


28. Synchronisation possible

On peut utiliser :
  • un sémaphore POSIX ;
  • un mutex process-shared ;
  • un sémaphore System V ;
  • des opérations atomiques adaptées ;
  • d'autres mécanismes de synchronisation.
Exemple :

Code: Select all

sem_wait(sem);

shared->counter++;

sem_post(sem);

29. Mémoire partagée + sémaphore POSIX

Un modèle fréquent consiste à utiliser :
  • un objet shm_open() pour les données ;
  • un sémaphore nommé avec sem_open() pour la synchronisation.
Exemple :

Code: Select all

sem_t *sem = sem_open(
    "/inside_sem",
    O_CREAT,
    0666,
    1
);
Puis :

Code: Select all

sem_wait(sem);

strcpy(shared_memory, "Hello");

sem_post(sem);

30. Sémaphore non nommé directement dans la zone partagée

On peut aussi placer un sémaphore non nommé dans la mémoire partagée.

Exemple :

Code: Select all

struct Shared {
    sem_t sem;
    int counter;
};
Après mapping :

Code: Select all

sem_init(
    &shared->sem,
    1,
    1
);
Le paramètre :

Code: Select all

1
indique que le sémaphore est partagé entre processus.


31. Exemple complet avec structure partagée

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <semaphore.h>

struct Shared {
    sem_t sem;
    int counter;
};

int main(void)
{
    int fd = shm_open(
        "/shared_struct",
        O_CREAT | O_RDWR,
        0666
    );

    if (fd == -1) {
        perror("shm_open");
        return EXIT_FAILURE;
    }

    if (ftruncate(fd, sizeof(struct Shared)) == -1) {
        perror("ftruncate");
        close(fd);
        return EXIT_FAILURE;
    }

    struct Shared *shared = mmap(
        NULL,
        sizeof(struct Shared),
        PROT_READ | PROT_WRITE,
        MAP_SHARED,
        fd,
        0
    );

    if (shared == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return EXIT_FAILURE;
    }

    close(fd);

    shared->counter = 0;

    if (sem_init(&shared->sem, 1, 1) == -1) {
        perror("sem_init");
        munmap(shared, sizeof(struct Shared));
        return EXIT_FAILURE;
    }

    sem_wait(&shared->sem);

    shared->counter++;

    sem_post(&shared->sem);

    sem_destroy(&shared->sem);
    munmap(shared, sizeof(struct Shared));
    shm_unlink("/shared_struct");

    return EXIT_SUCCESS;
}

32. Inspection sous Linux

Sous Linux, les objets de mémoire partagée POSIX sont généralement représentés dans un système de fichiers temporaire.

Ils sont souvent visibles dans :

Code: Select all

/dev/shm
On peut par exemple utiliser :

Code: Select all

ls -l /dev/shm
Un objet appelé :

Code: Select all

"/inside_shm"
peut apparaître comme :

Code: Select all

inside_shm
dans ce répertoire.


33. Le lien avec tmpfs

Sous Linux, /dev/shm est généralement basé sur :

Code: Select all

tmpfs
Les objets de mémoire partagée sont donc gérés via un système de fichiers en mémoire.

Ils restent néanmoins utilisés comme des objets IPC et non comme de simples fichiers classiques du programme.


34. Utilisation de fstat()

Comme shm_open() retourne un descripteur, les fonctions classiques travaillant sur des descripteurs peuvent souvent être utilisées.

Exemple :

Code: Select all

struct stat sb;

fstat(fd, &sb);
On peut alors récupérer :
  • la taille ;
  • certaines métadonnées ;
  • les permissions.

35. Redimensionnement

La taille d'un objet de mémoire partagée POSIX peut être modifiée avec :

Code: Select all

ftruncate()
Exemple :

Code: Select all

ftruncate(fd, 8192);
Cependant, modifier la taille de l'objet ne redimensionne pas automatiquement un mapping déjà existant.

Il peut être nécessaire de :
  • faire munmap() ;
  • puis refaire mmap() avec la nouvelle taille.

36. Persistance

Un objet de mémoire partagée POSIX peut continuer à exister après la fin du processus qui l'a créé tant que son nom n'a pas été supprimé.

Cela permet à un autre processus de l'ouvrir ensuite.

Le programme doit donc gérer correctement :

Code: Select all

shm_unlink()
pour éviter de laisser des objets inutiles.


37. POSIX Shared Memory vs System V Shared Memory

System V

Fonctions principales :

Code: Select all

shmget()
shmat()
shmdt()
shmctl()
Les segments sont identifiés par un identifiant numérique.

Exemple :

Code: Select all

int shmid;

POSIX

Fonctions principales :

Code: Select all

shm_open()
ftruncate()
mmap()
munmap()
shm_unlink()
Les objets sont identifiés par un nom.

Exemple :

Code: Select all

"/inside_shm"

38. Création : POSIX vs System V

System V

Code: Select all

int shmid = shmget(
    key,
    size,
    IPC_CREAT | 0666
);

POSIX

Code: Select all

int fd = shm_open(
    "/inside_shm",
    O_CREAT | O_RDWR,
    0666
);

ftruncate(fd, size);
Avec POSIX, la création de l'objet et la définition de sa taille sont deux étapes distinctes.


39. Mapping : POSIX vs System V

System V

Code: Select all

void *addr = shmat(
    shmid,
    NULL,
    0
);

POSIX

Code: Select all

void *addr = mmap(
    NULL,
    size,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    fd,
    0
);
POSIX utilise donc le mécanisme général de mémoire mappée Unix.


40. Suppression : POSIX vs System V

System V

Code: Select all

shmctl(
    shmid,
    IPC_RMID,
    NULL
);

POSIX

Code: Select all

shm_unlink(
    "/inside_shm"
);

41. POSIX Shared Memory vs Shared File Mapping

Un fichier classique peut également être utilisé comme backing store pour mmap().

Exemple :

Code: Select all

int fd = open(
    "shared.bin",
    O_CREAT | O_RDWR,
    0666
);
Puis :

Code: Select all

mmap(
    NULL,
    size,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    fd,
    0
);
Le principe du mapping est très proche de celui de shm_open().


42. Différence avec un fichier classique

Avec un fichier classique :
  • les données peuvent être destinées à rester sur le stockage ;
  • le fichier possède un chemin classique dans le système de fichiers.
Avec POSIX Shared Memory :
  • l'objet est destiné principalement à l'IPC ;
  • il possède un nom POSIX ;
  • il peut être stocké dans un système temporaire comme tmpfs sous Linux.

43. Trois grandes techniques de mémoire partagée

On peut donc distinguer :
  • System V Shared Memory ;
  • shared file mappings ;
  • POSIX Shared Memory.
Toutes permettent à plusieurs processus d'accéder à une même région mémoire.


44. Points communs entre les trois techniques
  • Chaque processus possède son propre mapping dans son espace virtuel.
  • Les adresses virtuelles peuvent être différentes.
  • La synchronisation doit être gérée séparément.
  • Les données peuvent être directement accessibles sans copie à chaque échange.
  • Les mappings peuvent être utilisés pour partager des structures complexes.

45. Différences importantes

System V

Utilise :

Code: Select all

key_t
shmid
shmget()
shmat()

File mapping

Utilise un véritable fichier comme backing store.

Exemple :

Code: Select all

open()
mmap()

POSIX Shared Memory

Utilise un objet nommé avec :

Code: Select all

shm_open()
puis les interfaces classiques :

Code: Select all

ftruncate()
mmap()

46. Taille de la région

Avec System V, la taille du segment est définie lors de la création.

Avec POSIX Shared Memory, on peut utiliser :

Code: Select all

ftruncate()
pour modifier la taille de l'objet.

Cela apporte une certaine flexibilité supplémentaire.


47. Synchronisation non fournie automatiquement

La mémoire partagée ne synchronise pas automatiquement les accès.

Deux processus peuvent écrire simultanément dans la même variable.

Exemple dangereux :

Code: Select all

shared->counter++;
Pour éviter les races, on doit utiliser une primitive appropriée.

Exemple :

Code: Select all

sem_wait(&shared->sem);

shared->counter++;

sem_post(&shared->sem);

48. Cohérence et visibilité

MAP_SHARED rend les modifications visibles entre les différents mappings de l'objet.

Cependant, cela ne remplace pas la synchronisation.

La visibilité de la mémoire et l'ordre logique des opérations doivent être gérés avec des primitives adaptées lorsque plusieurs processus accèdent simultanément aux données.


49. Avantages de POSIX Shared Memory
  • API cohérente avec open(), close(), ftruncate() et mmap().
  • Utilisation de noms lisibles.
  • Très bonnes performances pour de gros volumes de données.
  • Aucune copie explicite nécessaire entre producteurs et consommateurs.
  • Facile à combiner avec les sémaphores POSIX.
  • Taille modifiable avec ftruncate().
  • Inspection facile sous Linux via /dev/shm.

50. Inconvénients
  • La synchronisation doit être conçue séparément.
  • Les pointeurs stockés directement dans la zone peuvent être invalides dans un autre processus.
  • Une mauvaise gestion de la durée de vie peut laisser des objets persistants.
  • Les erreurs de synchronisation peuvent provoquer des races difficiles à diagnostiquer.
  • Pour de petits messages simples, une message queue ou un pipe peut être plus facile à utiliser.

51. Quand utiliser POSIX Shared Memory

Elle est particulièrement adaptée lorsque :
  • les processus échangent beaucoup de données ;
  • les performances sont importantes ;
  • on veut éviter les copies fréquentes ;
  • les processus doivent partager des structures ;
  • on dispose déjà d'un mécanisme de synchronisation adapté.

52. Quand préférer une Message Queue

Une file de messages est souvent plus simple lorsque :
  • les données sont naturellement organisées en messages ;
  • le volume est relativement faible ;
  • on souhaite des priorités ;
  • on ne veut pas gérer directement une région mémoire partagée.

53. Quand préférer un pipe

Un pipe est souvent adapté lorsque :
  • on souhaite un flux séquentiel simple ;
  • les processus ont une relation parent/enfant ;
  • aucune structure partagée complexe n'est nécessaire.

54. Exemple de cycle de vie complet

Code: Select all

int fd = shm_open(
    "/inside_shm",
    O_CREAT | O_RDWR,
    0666
);

ftruncate(fd, 4096);

void *addr = mmap(
    NULL,
    4096,
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    fd,
    0
);

close(fd);

/* utilisation */

munmap(addr, 4096);

shm_unlink("/inside_shm");

55. Erreurs fréquentes

Oublier ftruncate()

Créer l'objet sans lui donner une taille correcte avant mmap().


Utiliser MAP_PRIVATE

Cela empêche d'obtenir le comportement de mémoire partagée attendu.


Oublier la synchronisation

Plusieurs processus peuvent modifier les mêmes données simultanément.


Stocker des pointeurs absolus

Les adresses virtuelles peuvent différer entre les processus.


Oublier shm_unlink()

L'objet peut rester présent après la fin du programme.


Utiliser la zone après munmap()

Une fois le mapping retiré, l'adresse n'est plus valide.


56. Points importants à retenir
  • shm_open() crée ou ouvre un objet de mémoire partagée POSIX.
  • shm_open() retourne un descripteur de fichier.
  • Un nouvel objet possède initialement une taille nulle.
  • ftruncate() permet de définir sa taille.
  • mmap() permet de mapper l'objet dans l'espace virtuel.
  • MAP_SHARED est utilisé pour partager les modifications.
  • PROT_READ et PROT_WRITE contrôlent les accès.
  • fstat() peut permettre de récupérer la taille d'un objet existant.
  • close() ferme le descripteur mais ne détruit pas le mapping.
  • munmap() retire le mapping.
  • shm_unlink() supprime le nom de l'objet.
  • L'objet peut rester valide tant que des références subsistent.
  • Les différents processus peuvent obtenir des adresses virtuelles différentes.
  • Il faut éviter de partager directement des pointeurs absolus.
  • La synchronisation doit être ajoutée séparément.
  • Les sémaphores POSIX se combinent très bien avec la mémoire partagée.

57. Résumé

POSIX Shared Memory permet à plusieurs processus de partager directement une région mémoire commune.

Un objet est créé ou ouvert avec shm_open(), qui retourne un descripteur de fichier.

La taille de l'objet est généralement définie avec ftruncate(), puis l'objet est mappé avec mmap() en utilisant MAP_SHARED.

Une fois le mapping établi, les processus peuvent lire et écrire directement dans la zone partagée.

Le descripteur peut être fermé sans détruire le mapping.

munmap() retire le mapping local, tandis que shm_unlink() supprime le nom de l'objet.

Contrairement aux files de messages, la mémoire partagée ne fournit pas automatiquement de structure d'échange ni de synchronisation. Il est donc courant de la combiner avec des sémaphores ou des mutex process-shared.

Par rapport à System V Shared Memory, l'interface POSIX s'intègre mieux au modèle classique Unix basé sur les descripteurs, ftruncate() et mmap().

POSIX Shared Memory est particulièrement efficace pour échanger de gros volumes de données entre processus avec un coût minimal de copie.

Who is online

Users browsing this forum: No registered users and 1 guest