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

Prog C Linux : socket ou Sémaphore ou Pipe ou… Que choisir ?? Besoins d'avis et de conseils

7 réponses
Avatar
projlin
Bonjour,

Tout d'abord pardon si je ne suis pas dans le bon groupe mais je
penses que oui… Mais merci de me suggérer de poster ce message dans
d'autre groupe si vous avez une idée.

Voila je vais démarré un projet sous linux écrit en C.

Brièvement : 1 processus qui tourne en permanence. Je l'appelle GOD
;-)

Ce processus lance un programme : (fork() puis exec())

Ce programme/processus doit pouvoir envoyé et recevoir des info
depuis le processus GOD. De plus pour ne pas prendre 100% du cpu j'ai
besoins d'avoir des fonctionnalités de " Read bloquant "

Pour info : Je fait cela car GOD après sont lancement initialise une
carte hardware avec un API qui ne permet pas de gérer le "
multiprocess " : donc 1 seul processus peut avoir accès a cette carte
dans la machine.
Et moi jusqu'à 60 programmes différents doivent y accéder
simultanément : donc communication entre les 60 programmes et le
fameux GOD pour demander a GOD de faire " ceci ou cela " sur la carte…

Le paramètre a avoir : entre 1 et 240 processus peuvent communiquer
avec GOD.


Voilà maintenant a quoi j'ai penser durant toutes mes dernières nuit
blanches…

1) chaque programme possède une mémoire partagée. C'est assez facile a
mette en place puisque tous les processus sont créer par GOD, puis God
ou sont fils Ecrive dans différent champs de cette mémoire partagée.
La synchronisation étant faite par des sémaphores (pour avoir un Read
bloquant)
Résultat au plus fort de la musique : 240 Segment de mémoire partagée
et 240 sémaphores.

2) Les pipes : pareil mais pas de mémoire partagée et toutes les infos
transite par des pipes.
Résultat au plus fort de la musique : 240 pipes aller et 240 pipes
retours hummmmmmm
Je doutes un peut mais n'y connaissant rien 480 pipes ?? de plus le
système me parait moins efficace
Que le sémaphore et la mémoire partagée au niveau de la programmation
que l'on peut en faire.

3) Les sockets ?
La j'en suis encore a me documenter mais apparemment 240 socket
serveur et 240 sockets clients ??
Bon là un spécialiste socket peut peut-être m'éclairer…

4) Les queues ou files de messages (msgget etc etc)
La aussi j'en suis encore a me documenter mais ma foie cela parait
peut être le plus simple non ??
Y a un spécialiste dans la sale ??


LE PLUS IMPORTANT : LES PRIORITES DES CHOIX

1) Fiable a 100%, je ne peux pas me permettre la moindre perte de
messages
sinon le père ou le fils vont rester endormis a jamais…

2) La communication la plus rapide possible

3) Le système le moins gourmand en ressource machine. (poor litle
CPU…)

Toutes remarques ou suggestion seront les bienvenue


Gilles
Projlinux@hotmail.com

7 réponses

Avatar
Axel
moi je dirais memoire partagée

"" a écrit dans le message de
news:
Bonjour,

Tout d'abord pardon si je ne suis pas dans le bon groupe mais je
penses que oui. Mais merci de me suggérer de poster ce message dans
d'autre groupe si vous avez une idée.

Voila je vais démarré un projet sous linux écrit en C.

Brièvement : 1 processus qui tourne en permanence. Je l'appelle GOD
;-)

Ce processus lance un programme : (fork() puis exec())

Ce programme/processus doit pouvoir envoyé et recevoir des info
depuis le processus GOD. De plus pour ne pas prendre 100% du cpu j'ai
besoins d'avoir des fonctionnalités de " Read bloquant "

Pour info : Je fait cela car GOD après sont lancement initialise une
carte hardware avec un API qui ne permet pas de gérer le "
multiprocess " : donc 1 seul processus peut avoir accès a cette carte
dans la machine.
Et moi jusqu'à 60 programmes différents doivent y accéder
simultanément : donc communication entre les 60 programmes et le
fameux GOD pour demander a GOD de faire " ceci ou cela " sur la carte.

Le paramètre a avoir : entre 1 et 240 processus peuvent communiquer
avec GOD.


Voilà maintenant a quoi j'ai penser durant toutes mes dernières nuit
blanches.

1) chaque programme possède une mémoire partagée. C'est assez facile a
mette en place puisque tous les processus sont créer par GOD, puis God
ou sont fils Ecrive dans différent champs de cette mémoire partagée.
La synchronisation étant faite par des sémaphores (pour avoir un Read
bloquant)
Résultat au plus fort de la musique : 240 Segment de mémoire partagée
et 240 sémaphores.

2) Les pipes : pareil mais pas de mémoire partagée et toutes les infos
transite par des pipes.
Résultat au plus fort de la musique : 240 pipes aller et 240 pipes
retours hummmmmmm
Je doutes un peut mais n'y connaissant rien 480 pipes ?? de plus le
système me parait moins efficace
Que le sémaphore et la mémoire partagée au niveau de la programmation
que l'on peut en faire.

3) Les sockets ?
La j'en suis encore a me documenter mais apparemment 240 socket
serveur et 240 sockets clients ??
Bon là un spécialiste socket peut peut-être m'éclairer.

4) Les queues ou files de messages (msgget etc etc)
La aussi j'en suis encore a me documenter mais ma foie cela parait
peut être le plus simple non ??
Y a un spécialiste dans la sale ??


LE PLUS IMPORTANT : LES PRIORITES DES CHOIX

1) Fiable a 100%, je ne peux pas me permettre la moindre perte de
messages
sinon le père ou le fils vont rester endormis a jamais.

2) La communication la plus rapide possible

3) Le système le moins gourmand en ressource machine. (poor litle
CPU.)

Toutes remarques ou suggestion seront les bienvenue


Gilles



Avatar
Laurent Wacrenier
écrit:
Ce processus lance un programme : (fork() puis exec())


vfork()

1) chaque programme possède une mémoire partagée. C'est assez facile a
mette en place puisque tous les processus sont créer par GOD, puis God
ou sont fils Ecrive dans différent champs de cette mémoire partagée.
La synchronisation étant faite par des sémaphores (pour avoir un Read
bloquant)
Résultat au plus fort de la musique : 240 Segment de mémoire partagée
et 240 sémaphores.


Pas terrible, tu vas faire des boucles actives pour savoir où piocher
l'information. Si tu veux éviter celà, il faut que tu utilise un pipe
pour avertir le maître qu'il a quelque chose à lire.

2) Les pipes : pareil mais pas de mémoire partagée et toutes les infos
transite par des pipes.
Résultat au plus fort de la musique : 240 pipes aller et 240 pipes
retours hummmmmmm
Je doutes un peut mais n'y connaissant rien 480 pipes ?? de plus le
système me parait moins efficace
Que le sémaphore et la mémoire partagée au niveau de la programmation
que l'on peut en faire.


Pourquoi ce serait moins efficace ?

Il es possible que le noyau limite le nombre de descripteurs ouverts
par un processus à 255. Dans ce cas il est parfois possible d'agmenter
la limite avec setrlimit().

Si tes messages sont courts (mois de 512 octets), tu peux n'utiliser
qu'un seul pipe en écriture, les paquets ne seront pas fragmentés. Il
faudra indiquer quel client envoie le message pour lui renvoyer la
réponse.

Sinon, utilise les sockets, c'est plus paramétrable (avec
setsockopt()) et bi-directionnel.

3) Les sockets ?
La j'en suis encore a me documenter mais apparemment 240 socket
serveur et 240 sockets clients ??
Bon là un spécialiste socket peut peut-être m'éclairer


Les sockets sont bi-directionnelles, à part ça, crée les comme des
pipes mais utilise socketpair() avec le protocole PF_UNIX ou PF_LOCAL.
Elle seront connectées et il n'y aura pas de perte de données.

L'interêt des sockets, c'est que si le serveur ou le client meure,
l'autre extremité peut le detecter et il ne reste plus de trace dans
le système à la fin.

Également, celà autorise simplement une extension de l'application
pour accueuilir des clients externes.

4) Les queues ou files de messages (msgget etc etc)
La aussi j'en suis encore a me documenter mais ma foie cela parait
peut être le plus simple non ??
Y a un spécialiste dans la sale ??


c'est probablement meilleur que la mémoire partagée car les esclaves
peuvent envoyer des commandes en rafale (sans attendre la réponse du
maître) et ne pas se soucier du vérouillage. Par contre si le maître
meure, ils ne seront pas avertis.

Avatar
Jean-Yves LENHOF
Voila je vais démarré un projet sous linux écrit en C.

Brièvement : 1 processus qui tourne en permanence. Je l'appelle GOD ;-)

Ce processus lance un programme : (fork() puis exec())

Ce programme/processus doit pouvoir envoyé et recevoir des info depuis
le processus GOD. De plus pour ne pas prendre 100% du cpu j'ai besoins
d'avoir des fonctionnalités de " Read bloquant "

Pour info : Je fait cela car GOD après sont lancement initialise une
carte hardware avec un API qui ne permet pas de gérer le " multiprocess
" : donc 1 seul processus peut avoir accès a cette carte dans la
machine. Et moi jusqu'à 60 programmes différents doivent y accéder
simultanément : donc communication entre les 60 programmes et le fameux
GOD pour demander a GOD de faire " ceci ou cela " sur la carte…

Le paramètre a avoir : entre 1 et 240 processus peuvent communiquer
avec GOD.


Voilà maintenant a quoi j'ai penser durant toutes mes dernières nuit
blanches…

1) chaque programme possède une mémoire partagée. C'est assez facile
a mette en place puisque tous les processus sont créer par GOD, puis
God ou sont fils Ecrive dans différent champs de cette mémoire
partagée. La synchronisation étant faite par des sémaphores (pour
avoir un Read bloquant)
Résultat au plus fort de la musique : 240 Segment de mémoire partagée
et 240 sémaphores.

2) Les pipes : pareil mais pas de mémoire partagée et toutes les infos
transite par des pipes.
Résultat au plus fort de la musique : 240 pipes aller et 240 pipes
retours hummmmmmm
Je doutes un peut mais n'y connaissant rien 480 pipes ?? de plus le
système me parait moins efficace
Que le sémaphore et la mémoire partagée au niveau de la programmation
que l'on peut en faire.

3) Les sockets ?
La j'en suis encore a me documenter mais apparemment 240 socket serveur
et 240 sockets clients ??
Bon là un spécialiste socket peut peut-être m'éclairer…

4) Les queues ou files de messages (msgget etc etc) La aussi j'en suis
encore a me documenter mais ma foie cela parait peut être le plus
simple non ??
Y a un spécialiste dans la sale ??


LE PLUS IMPORTANT : LES PRIORITES DES CHOIX

1) Fiable a 100%, je ne peux pas me permettre la moindre perte de
messages sinon le père ou le fils vont rester endormis a jamais…

2) La communication la plus rapide possible

3) Le système le moins gourmand en ressource machine. (poor litle
CPU…)


Oula...ca me rappelle vaguement des choses ce type de programmes...


Une fois ton choix fait.... cela pourra peut-etre t'aider

http://deptinfo.cnam.fr/Enseignement/CycleProbatoire/CDI/ProjetCDI/CoursRazac.pdf

JYL

Avatar
projlin
Merci pour ta réponse et on aide.

Pour la mémoire partagée
Pas terrible, tu vas faire des boucles actives pour savoir où piocher
l'information. Si tu veux éviter celà, il faut que tu utilise un pipe
pour avertir le maître qu'il a quelque chose à lire.


Oui enfin je pensais sans se cas là synchroniser avec un sémaphore ??
La question subsidiaire de ce cas est : est-ce que un sémaphore
positionné par
un processus A peut être relâché par un processus B ????

et plus génériquement pour tous les systéme envisagé y a-t-il
possibilité par exemple pour un pipe
une queue de message, un socket : que le serveur lise un pipe ou un
socket et que tous les autre processus
écrive dans celui là ?

dans ce cas le serveur a un file d'attente d'ordre, que ce soient une
queue, un pipe ou un socket
et il les lis séquentiellement et les traites.

Le problème des commandes en rafale ne se pose pas car toutes
commandes doivent mettre le processus client
en sommeil jusqu'à la réalisation de cette commande.

Par contre pour les commandes elles peuvent avoir une taille
importante enfin entre 100 octets et 2Ko

Si je doutais de la fiabilité des pipes et des queues de messages
c'est parce que j'ai lu qu'il n'était pas possible de connaître leurs
limites :

Taille maxi des pipes ?
Nombre maxi d'éléments par pipes ?
Pareil pour les queues ?

Si tu sais comment interpréter j'ai trouvé cela … en tapant sysctl -a

kernel.sem = 250 32000 32 128

kernel.msgmnb = 16384
kernel.msgmni = 16
kernel.msgmax = 8192

kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.shmmax = 33554432


Ma problématique est autant le transfert de donnée vers le serveur que
la synchro.

Voilà comment je vois le fonctionnement.

Le serveur est en sommeil attente d'une nouvelle commande (lecture
bloquante ou autre…)

Un client envoie une commande
Le client est en sommeil (lecture bloquante ou autre…)



Le serveur effectue cette commande
Le serveur réveille le client pour qu'il il vient de travailler.

Le serveur est en sommeil attente d'une nouvelle commande (lecture
bloquante ou autre…)


Avatar
Laurent Wacrenier
écrit:
Pas terrible, tu vas faire des boucles actives pour savoir où piocher
l'information. Si tu veux éviter celà, il faut que tu utilise un pipe
pour avertir le maître qu'il a quelque chose à lire.


Oui enfin je pensais sans se cas là synchroniser avec un sémaphore ??
La question subsidiaire de ce cas est : est-ce que un sémaphore
positionné par
un processus A peut être relâché par un processus B ????


Oui, mais utiliser des sémaphores pour synchroniser les sémaphores
ça devient tordu.

et plus génériquement pour tous les systéme envisagé y a-t-il
possibilité par exemple pour un pipe
une queue de message, un socket : que le serveur lise un pipe ou un
socket et que tous les autre processus
écrive dans celui là ?


Oui, il faut que les données écrites ne soit pas mélangées. Pour les
messages, il ne doit pas y avoir de soucis. Pour les pipes, c'est le
cas si la taille du paquet est inferieures à une limite constante
(PIPE_BUF) qui vaut au moins 512 octets. Pour les sockets, je ne suis
pas sûr (c'est possibles qu'elles ne mélangent jamais), mais comme
elles sont bi-directionnelles, ça ne sert pas à grand chose de faire
comme celà (on se reveille sur une entrée avec un select() ou un
poll())

Si tu fais des écritures plus grosses sur un pipe, il vaut vérouiller.

dans ce cas le serveur a un file d'attente d'ordre, que ce soient une
queue, un pipe ou un socket
et il les lis séquentiellement et les traites.

Le problème des commandes en rafale ne se pose pas car toutes
commandes doivent mettre le processus client
en sommeil jusqu'à la réalisation de cette commande.

Par contre pour les commandes elles peuvent avoir une taille
importante enfin entre 100 octets et 2Ko

Si je doutais de la fiabilité des pipes et des queues de messages
c'est parce que j'ai lu qu'il n'était pas possible de connaître leurs
limites :

Taille maxi des pipes ?


normalement, leur nombre (comme pour les sockets) est limité par le
nombre de descripteurs de fichiers ouvrables.

Nombre maxi d'éléments par pipes ?


La taille de la queue est dépendate du système, mais ce n'est pas ton
problème, si elle est pleine, l'écrivain attend.

Pareil pour les queues ?


Tu devrais pouvoir occuper toute le mémoire accessible.

Si tu sais comment interpréter j'ai trouvé cela … en tapant sysctl -a

kernel.sem = 250 32000 32 128

kernel.msgmnb = 16384
kernel.msgmni = 16
kernel.msgmax = 8192

kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.shmmax = 33554432


ça a l'air d'être les limites des ICP System V. Elles sont globales et
dépendantes du système. Soit tu les remontes à la valeur que tu veux,
soit tu géres la fait quel les écritures peuvent échouer (et qu'il
faudra les recommencer un peu plus tard)

Ma problématique est autant le transfert de donnée vers le serveur que
la synchro.

Voilà comment je vois le fonctionnement.

Le serveur est en sommeil attente d'une nouvelle commande (lecture
bloquante ou autre…)


Avec des sockets (ou plusieurs pipe) select() ou poll() plutôt qu'une
lecture bloquante.

Un client envoie une commande
Le client est en sommeil (lecture bloquante ou autre…)




lecture bloquante (ou attente de message).

Le serveur effectue cette commande
Le serveur réveille le client pour qu'il il vient de travailler.


il suffit qu'il écrive le résultat (ou n'importe quoi s'il n'y a pas
de résultat)

Le serveur est en sommeil attente d'une nouvelle commande (lecture
bloquante ou autre…)


Comme tu fais des vfork/exec, avec des pipe ou des sockets, n'oublie
pas de fermer les descripteurs dont les escalves ne se servent pas. Le
plus simple est de mettre et retirer le flag close-on-exec (avec
fcntl). Place le descripteur à un endroit attendu par l'esclave (par
exemple stdin/stdout) avec dup2 comme ça il n'aura pas besoin de
courrir après.



Avatar
projlin
Comme tu fais des vfork/exec, avec des pipe ou des sockets, n'oublie
pas de fermer les descripteurs dont les escalves ne se servent pas. Le
plus simple est de mettre et retirer le flag close-on-exec (avec
fcntl). Place le descripteur à un endroit attendu par l'esclave (par
exemple stdin/stdout) avec dup2 comme ça il n'aura pas besoin de
courrir après.


lorsque je fait un fork puis un exec dans mon prog
au moment de l'exec tout se ferme tout seul de toute facons ? non ?
un exec appelle bien un Exit non ??

bon donc si je résume le mieux dans mon cas est de prendre les queue
de messages ou les socket ???? mais ou puis-je trouver des
informations la taille et le nombre maximum ???

peut tu aussi m'eclairer sur le fait que tu parle de bidirectionel
pour les socket et pas pour les queue de message ????

Avatar
Laurent Wacrenier
écrit:
Comme tu fais des vfork/exec, avec des pipe ou des sockets, n'oublie
pas de fermer les descripteurs dont les escalves ne se servent pas. Le
plus simple est de mettre et retirer le flag close-on-exec (avec
fcntl). Place le descripteur à un endroit attendu par l'esclave (par
exemple stdin/stdout) avec dup2 comme ça il n'aura pas besoin de
courrir après.


lorsque je fait un fork puis un exec dans mon prog
au moment de l'exec tout se ferme tout seul de toute facons ? non ?
un exec appelle bien un Exit non ??


Non, lors d'un exec, seuls les descripteurs avec le flag close-on-exec
sont fermés. Lors d'une ouverture (avec open, pipe, socket, etc.), ce
flag n'est pas mis (il faut le mettre avec fcntl) Tu aurais du mal à
passer des socket et des pipe si tout était fermé.

bon donc si je résume le mieux dans mon cas est de prendre les queue
de messages ou les socket ???? mais ou puis-je trouver des
informations la taille et le nombre maximum ???


Je le ferais avec des sockets mais c'est possible avec des messages.
Il faut alors ouvrir autant de queues de messages que de processus (et
c'est lourd). tu peux avoir les parametres sur les socket avec
getrlimit (nombre de descripteurs) et getsockopt (taille des buffers,
etc.) mais pour une écriture bloquante, la taille du buffer n'est pas
très importante (tu devrais cependant mettre un buffer assez grand
pour que le père n'attende pas trop pour envoyer la réponse) Pour les
messages, il faut interroger le noyau et il n'y a pas de fonction
standard.

peut tu aussi m'eclairer sur le fait que tu parle de bidirectionel
pour les socket et pas pour les queue de message ????


Une socket a deux queues, une dans chaque sens. Ce n'est pas toujours
le cas avec les pipes et jamais avec les messages.