Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Partage d'une map entre différents processus via mmap

4 réponses
Avatar
Helfer Thomas
Bonjour,

cette question est sans doute à la limite du champ de ce groupe, je m'en
excuse. Novice en terme de programmation concurrente, ma question sera
peut-être également très naïve.

J'aimerai savoir si il est possible de partage une map entre deux
processus en la plaçant dans une zone de mémoire partagée déclarée à
l'aide de la fonction posix mmap.

void * ptr = mmap(0,sizeof(std::map),PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1,0);

std::map* m = new (ptr) std::map();

Ce code a t'il une quelconque chance de marcher ? Question subsidiaire :
dans quel espace mémoire sont alloués les objets de la map ?

Cordialement,

Helfer Thomas

4 réponses

Avatar
Loïc Joly
void * ptr = mmap(0,sizeof(std::map),PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1,0);

std::map* m = new (ptr) std::map();

Ce code a t'il une quelconque chance de marcher ? Question subsidiaire :
dans quel espace mémoire sont alloués les objets de la map ?


Il se peut que oui (j'ai toujours été surpris de voir sur SGI que ce
code pourtant faux a l'air de marcher pour peu qu'on ne touche pas trop
à la map...), mais dans ce cas, joue au loto... L'idée pour faire
marcher proprement ça, c'est de spécifier dans ta map un allocateur que
tu aura créé à l'occasion, et qui allouera lui aussi la mémoire dans la
zone partagée. Par contre, il vaut mieux prévoir dès le début une taille
plus grande pour ta zone, et faire que ton allocateur la découpe à sa guise.

--
Loïc

Avatar
James Kanze
On Apr 12, 9:16 pm, Helfer Thomas wrote:

cette question est sans doute à la limite du champ de ce groupe, je m'en
excuse. Novice en terme de programmation concurrente, ma question sera
peut-être également très naïve.

J'aimerai savoir si il est possible de partage une map entre deux
processus en la plaçant dans une zone de mémoire partagée déclar ée à
l'aide de la fonction posix mmap.

void * ptr = mmap(0,sizeof(std::map),PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1,0);

std::map* m = new (ptr) std::map();

Ce code a t'il une quelconque chance de marcher ?


Non. Pour commencer, il ne doit pas compiler, parce que
sizeof(std::map) n'a pas de sens. Mais plus généralement : il
faudrait allouer beaucoup plus, pour que le std::map ait de la
mémoire partagée pour ses allocations ; il faudrait créer un
allocateur qui utilise cette mémoire partagée ; il faudrait
aussi s'assurer que le contenu du map utilise cet allocateur (si
les types ont besoin de la mémoire dynamique).

En principe, quelque chose du genre :

void* p ; // doit être global :-(
typedef std::basic_string< char,
std::char_traits< char >,
MyAllocator< p, char > >
SharedString ;
typedef std::map< SharedString,
int,
std::less< SharedString >,
MyAllocator< p, std::pair< SharedString const,
int > >
SharedMap ;

p = mmap( 0, lots, ... ) ;
SharedMap* pMap = new ( MyAllocator< p >() ) SharedMap( a ) ;

doit être possible. Mais je ne l'ai jamais essayé, et j'imagine
que la définition de MyAllocator ne doit pas être triviale.

Si j'ai compris correctement, il doit même être possible de le
faire marcher dans le cas où la mémoire est mappée à des
adresses différentes dans les différentes processus. Encore que
j'ai mes doutes : MyAllocator<T>::reference doit être une vraie
référence, et vue que sous les draps, une référence est un
pointeur...

Aussi, il est possible de donner de l'état à un allocateur,
c-à-d de faire que le p, ci-dessus, soit une variable membre, et
non un paramètre d'instantiation de l'allocateur. Mais je ne
crois pas qu'un support complet pour ceci soit exigé ; je sais
que Dinkumware dit de le supporter, mais la façon qu'il le dit
suggère fortement que c'est que question de qualité de
l'implémentation. (Mais si j'ai bien compris, ça ne doit poser
de problèmes que si tu instanties MyAllocator avec plusieurs p
différents, et melange des objets des différentes instances.)

Question subsidiaire :
dans quel espace mémoire sont alloués les objets de la map ?


Dans l'espace déterminer par son allocateur. L'allocateur par
défaut utilise ::operator new, et donc, le heap global du
processus. Qui n'est pas partagé.

PS: Si tu arrives à faire marcher quelque chose avec les
allocateurs, fais-nous savoir. Même, si possible, décrire
exactement ce que tu as dû faire, sur une page de Web
quelque part. L'utilisation des allocateurs est un des
aspects le plus exotiques de la bibliothèque standard, et
probablement parmi les moins compris.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Helfer Thomas
Merci pour vos deux réponses qui confirment mes craintes (d'autant qu'un
test rapide m'avait brillamment conduit à un segfault...).

P.S. : James, l'écriture d'un allocateur partagé me semble un défi très
intéressant et qui m'apprendrait sans doute beaucoup sur ces bêtes
étranges. Je te tiendrai au courant si jamais je trouve le temps de m'y
plonger.

Le Thu, 12 Apr 2007 21:16:06 +0200, Helfer Thomas a écrit :

Bonjour,

cette question est sans doute à la limite du champ de ce groupe, je m'en
excuse. Novice en terme de programmation concurrente, ma question sera
peut-être également très naïve.

J'aimerai savoir si il est possible de partage une map entre deux
processus en la plaçant dans une zone de mémoire partagée déclarée à
l'aide de la fonction posix mmap.

void * ptr = mmap(0,sizeof(std::map),PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1,0);

std::map* m = new (ptr) std::map();

Ce code a t'il une quelconque chance de marcher ? Question subsidiaire :
dans quel espace mémoire sont alloués les objets de la map ?

Cordialement,

Helfer Thomas


Avatar
Loïc Joly
Merci pour vos deux réponses qui confirment mes craintes (d'autant qu'un
test rapide m'avait brillamment conduit à un segfault...).

P.S. : James, l'écriture d'un allocateur partagé me semble un défi très
intéressant et qui m'apprendrait sans doute beaucoup sur ces bêtes
étranges. Je te tiendrai au courant si jamais je trouve le temps de m'y
plonger.


J'ai oublié de dire.... D'autres l'ont déjà fait. Donc, à moins que le
défi t'intéresse, tu peux regarder boost::interprocess (accepté, devrait
être dans la prochaine version, dispo sur cvs) :
http://ice.prohosting.com/newfunk/boost/libs/interprocess/doc/html/index.html

--
Loïc