Précédent   Forum des professionnels en informatique > Systèmes > Linux
Linux Forum d'entraide sur le système Linux. Avant de poster -> Tutoriels Linux, F.A.Q Linux
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/08/2011, 17h28   #1
Candidat au titre de Membre du Club
 
Inscription : juillet 2009
Messages : 35
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 35
Points : 14
Points : 14
Par défaut Problèmes de FIFO

Bonjour,

J'ai un petit problème avec les FIFOs, dont j'ai du mal à comprendre le fonctionnement... ou tout du moins à utiliser leur fonctionnement. Je m'explique.

J'ai 2 applications A et B qui ont besoin de communiquer. Pour cela, j'ai mis en place 2 FIFOs, une A>B (F1) et une B>A (F2). J'ai pas de problème pour ouvrir les FIFOs, mais c'est dans la communication que les problèmes apparaissent.

A envoie une commande sur F1 et attend une réponse sur F2. Problème, de son côté, B ne reçoit rien sur F1 ! Du coup, B est bloquée en attendant une commande, et A en attendant une réponse.... Au bout d'un moment, j'arrête A, pour voir ce qui ne va pas. Et je constate qu'à ce moment précis, B accède aux données que A avait envoyées dans F1.

Avez-vous une idée d'où pourrait venir le problème ?

Merci de m'avoir lu !
cycloop est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 12/08/2011, 20h27   #2
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 537
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 537
Points : 7 749
Points : 7 749
là comme ça moi non plus j'ai rien compris à ton besoin....

un fifo c'est first in first out unidirectionnel
donc a -> b et APRES tu peux faire dans l'autre sens mais pas en même temps.
frp31 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 20h28   #3
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 537
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 537
Points : 7 749
Points : 7 749
là comme ça moi non plus j'ai rien compris à ton besoin....

un fifo c'est first in first out unidirectionnel
donc a -> b et APRES tu peux faire dans l'autre sens mais pas en même temps.

sauf à passer par des moyens détournés ....mais dans ce cas la le fifo devient une mauvaise solution et un socket et plus approprié. par exemple
frp31 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/08/2011, 09h23   #4
Candidat au titre de Membre du Club
 
Inscription : juillet 2009
Messages : 35
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 35
Points : 14
Points : 14
Bonjour !

Tout d'abord merci de te pencher sur mon problème !

Effectivement, les FIFOs sont unidirectionnelles. C'est la raison pour laquelle j'en ai deux ! Sur la première FIFO, A envoie des commandes à B. Sur la seconde FIFO, B renvoie le résultat des commandes.
cycloop est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 16/08/2011, 11h33   #5
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 537
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 537
Points : 7 749
Points : 7 749
mais c'est pas possible ça, puisque tant que la liaison est ouverte dans 1 sens, tu peux pas en avoir une en // dans le sens inverse.
frp31 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/08/2011, 13h19   #6
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 1 375
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 33
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : octobre 2008
Messages : 1 375
Points : 2 034
Points : 2 034
Montre nous ton code.
matafan est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 16/08/2011, 14h39   #7
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 1 375
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 33
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : octobre 2008
Messages : 1 375
Points : 2 034
Points : 2 034
J'aimerai bien savoir qui s'amuse à mettre des -1 sans raison. Pas juste dans ce sujet, mais dans d'autres aussi. Parfois même sur le premier post d'un sujet, qui pourtant pose une question légitime et relativement bien rédigée. On en voit de plus en plus et ça a le don de m'énerver.
matafan est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 16/08/2011, 15h57   #8
Candidat au titre de Membre du Club
 
Inscription : juillet 2009
Messages : 35
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 35
Points : 14
Points : 14
Voilà les parties du code relatives aux FIFOs. Le premier programme est en Python, le second est en C/C++. "fcmd" et "fdata" sont les noms des deux fifos, que j'ai créées en utilisant la commande "mkfifo --mode=a+rw"


Application "client" :
Code Python :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class client:
 
	def send(command):
		self.cmd_fifo.write(command)
 
	def receive():
		data=""
		while data=="":
			data=self.data_fifo.readline()
			time.sleep(1)
		return data
 
	def run():
		self.cmd_fifo=open("./fcmd","w")
		self.data_fifo=open("./fdata","r")
 
		self.send("ma_commande")
		data = self.receive()
Application "serveur" :
Code C/C++ :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
char* execute(char* command);
 
void read_cmd(char* buf,int buf_size, FILE* fifo) {
	char c=0;
	int it=0;
 
	while((c=fgetc(fifo))==EOF) {
		sleep(1);
	}
 
	do {
		buf[it]=c;
		it++;
	} while(it<buf_size && (c=fgetc(fifo))!=EOF);
}
 
void send_data(char* data,int data_size, FILE* fifo) {
	int it=0;
	for(it=0;it<data_size;it++) {
		fwrite(&buf[i],sizeof(char),1,fifo);
	}
}
 
int main(argc, char* argv[]) {
	FILE* cmd_fifo = fopen("./fcmd","r");
	FILE* data_fifo = fopen("./fdata","w");
	char cmd[100];
	char data[100];
 
	if(cmd_fifo==NULL || data_fifo==NULL) {
		fprintf(stderr,"FIFO error\n");
		exit(-1);
	}
 
	while(1) {
		memset(cmd,0,100);
		memset(data,0,100);
		read_cmd(cmd,100,cmd_fifo);
		data=execute(cmd);
		send_data(data,100,data_fifo);
	}
 
	return 0;
}

Désolé si je ne mets pas le code original, le projet est assez confidentiel...

Les deux applications se bloquent dans leur fonction de réception de donnée. La première considère avoir envoyé ses données et attend la réponse, tandis que la seconde reste en attente de la commande, qu'elle semble n'avoir pas reçue. Lorsqu'on tue manuellement l'application cliente, l'application serveur reçoit alors la commande et la traite correctement.

Cela pourrait bien s'expliquer si la lecture était bloquée par une ouverture en écriture, mais je n'ai lu nulle part que c'était le cas. Des avis ?

J'espère avoir été clair, et si jamais vous avez besoin d'informations supplémentaires, je reste à l'écoute ! Merci encore
cycloop est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 16/08/2011, 17h44   #9
Candidat au titre de Membre du Club
 
Inscription : juillet 2009
Messages : 35
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 35
Points : 14
Points : 14
Citation:
Envoyé par frp31 Voir le message
mais c'est pas possible ça, puisque tant que la liaison est ouverte dans 1 sens, tu peux pas en avoir une en // dans le sens inverse.
Que veux-tu dire ? Que Linux n'est pas prévu pour l'utilisation de 2 FIFOS en même temps ? Il s'agit de 2 FIFOs différentes, avec chacune un sens dédié. Je vois a priori pas où est le problème avec une telle architecture...
cycloop est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 16/08/2011, 22h03   #10
Expert Confirmé Sénior
 
Avatar de frp31
 
Homme francois
Ingénieur systèmes et réseaux
Inscription : juillet 2006
Messages : 3 537
Détails du profil
Informations personnelles :
Nom : Homme francois
Âge : 35
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur systèmes et réseaux
Secteur : Aéronautique - Marine - Espace - Armement

Informations forums :
Inscription : juillet 2006
Messages : 3 537
Points : 7 749
Points : 7 749
aucun OS ne permet jamais ça le fifo reste tjrs quoi qu'il arrive unidirectionnel d'objet à objet ..... on peut en faire autant qu'on veut mais si deux ou plus sont sur les memes sources/destination ça marche pas... c'est pourquoi la méthode est mauvaise (après reflection) la solution :
il faut refaire les codes pour utiliser un socket
frp31 est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 13h10   #11
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 1 375
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 33
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : octobre 2008
Messages : 1 375
Points : 2 034
Points : 2 034
On peut tout à fait utiliser deux fifo (pipe ou fichier fifo) pour communiquer bidirectionnellement entre deux processus.

Ca ressemble à un problème de bufferisation. Essaie d'ajouter un self.cmd_fifo.flush() (je ne connais pas python mais tu vois l'idée) après le write() dans ton send(), et un fflush(fifo) après le write() dans ton send_data().

Une autre solution pour éviter d'avoir à flusher explicitement les streams après les write() est de les passer en mode non bufferisé. En C tu fais un setbuf(stream, NULL). En python apparemment tu peux ajouter l'argument 0 au open() pour demander un buffer de taille nulle.
matafan est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 17/08/2011, 13h21   #12
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 1 375
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 33
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : octobre 2008
Messages : 1 375
Points : 2 034
Points : 2 034
Aussi, dans read_cmd(), la boucle sur le sleep(1) ne sert à rien. De toute façon le fgetc() bloquera tant que personne n'aura écrit dans le fichier.
matafan est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 19/08/2011, 12h55   #13
Candidat au titre de Membre du Club
 
Inscription : juillet 2009
Messages : 35
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 35
Points : 14
Points : 14
Je vous remercie pour vos conseils. La mise en place des flsuh n'a rien changé cependant... Ce qui m'amène, à nouveau dans l'impasse...

Du coup je passerais bien aux sockets, mais je n'y connais rien. Pouvez-vous me suggérer des tutos/cours/docs pour que j'y parvienne rapidement ?
cycloop est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 19/08/2011, 13h58   #14
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 1 375
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 33
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : octobre 2008
Messages : 1 375
Points : 2 034
Points : 2 034
En fait en regardant ton code d'un peu plus près je pense que ton problème c'est simplement que tu ne fermes pas self.cmd_fifo après le write(). Du coup le fread() du serveur ne retourne jamais EOF. Et même chose dans l'autre sens, le serveur doit fermer data_fifo après avoir écrit ses données.
matafan est déconnecté   Envoyer un message privé Réponse avec citation 01
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 15h41.


 
 
 
 
Partenaires

Hébergement Web