Tubes nommes en c++

Fermé
mogeb - 8 févr. 2009 à 07:54
 mogeb - 8 févr. 2009 à 23:11
Bonjour a tous.
Voila je developpe un programme en c++ et j ai beaucoup de misere a utiliser les tubes nommes. Normalement un processus doit creer un tube nomme avec un mkfifo puis l'ouvrir et finalement ecrire dedans.
lorsque je lance mon programme il "bloque" quelque part je ne sais pas ou, mais je sais que c'est lorsque vient le temps de manipuler le tube nomme.
while(...){
...
mkfifo(miniControleur->nom_.c_str(), 0777);
....}

int fd;
fd=open(vectMiniControl[ligne]->nom_.c_str(), O_WRONLY);
if(fd!=-1){
cout<<"ouverture reussie"<<endl;
write(fd, &secondes,sizeof(secondes));
exit(1);
}
else if(fd==0){
cout<<"Desole, tube non disponible"<<endl;
return -1;
}
close(fd);
return 0;
//fin du programme
voici l'extrait de mon code, la ou vient la manipulation des tubes. vectMiniControl[ligne]->nom_ est un string. en fait aucun des deux messages n'apparait et mon programme ne se termine pas. Tout aide est fortement appreciee.
Merci.
A voir également:

7 réponses

Bon finalement c'est normal que ça bloque dans la fonction 'open'; j'aurais dû m'en souvenir, mais on pratique pas assez souvent.
La fonction 'open' ouvre le tube et attend que l'autre extrémité soit ouverte... si l'on ne veut pas attendre, il faut ouvrir avec l'attribut 'O_WRONLY | O_NONBLOCK'; dans ce cas la main est immédiatement rendue avec l'erreur -1.
Nota: l'autre extrémité doit être ouverte avec l'attribut complémentaire (lecture avec écriture, écriture avec lecture, lecture-écriture avec lecture-écriture).
Bon courage.
1
Si aucune des deux chaînes n'est affichée, c'est parce qu'on atteint pas la sortie de la fonction 'open'.
Mais est-tu sûr de sortir du bloc 'while'? Mets un 'printf' à la sortie de la boucle.
D'autre part il serait bon de tester la fonction 'mkfifo' (0 si ok, -1 si erreur).
0
Salut, merci pour ta reponse.
J'ai effectivement inclut un test pour la validation de la fonction mkfifo, et la boucle while() se termine apres 3 iterations (c'est un while(!fichier.eof()). Tu dis qu'on atteint jamais la fin de la fonction open, a quoi est du le probleme?
Merci beaucoup.
0
Et elle dit quoi la fonction 'mkinfo' dans chaque itération ?
Etant donné qu'aucune des 2 chaînes n'est affichée, cela signifie que le test 'if (fd!=-1)' n'est jamais exécuté, donc on bloque avant.
Si l'on a atteint la fonction 'open', c'est elle qui bloque... et là je ne comprends pas pourquoi car cette fonction ne doit pas bloquer; si 'open' n'est pas réalisé, la main est rendue avec une erreur. C'est pour cela que je pensais qu'on ne sortait pas de la boucle.
Tu fais un 'while (!fichier.eof())', mais quelle est la relation entre 'fichier' et 'mkfifo'
0
Salut,
la relation entre le fichier et les tubes c'est que je dois creer des fichiers speciaux (tubes nommes) dont le nom de chacun d'eux est lu a partir d'un fichier:
string nom;
fichier>>nom;
mkfif(nom.c_str(),0777);

c'est assez simple et je ne pene pas que le probleme soit quelque part par la. si je fais un printf() tout de suite avant la fonction open, ce printf s'execute. Pour la verification du mkfifo j'ai fait un petit truc dans le bloc while{} du genre:
int n=mkfifo(miniControleur->nom_.c_str(), 0777);
if(n==0)
cout<<"ca marche"<<endl;
else
cout<<"ca marche pas"<<endl;
et j'ai 3 fois "ca marche" qui s'affiche lors de l'execution. Je sais pas, est-ce que la fonction c_str() derange lors de la creation du tube? Ou cette meme fonction derange-t-elle lors de l'ouverture de cette pipe? Normalement non parce que c_str() retourne un objet de type const char*, tout comme doit etre le type du nom du fichier a ouvrir dans le open(). Est-ce possible qu'il y ait une erreur externe au code? Mais comme quoi?
Merci beaucoup.
0
Je ne vois pas ce qui cloche.
Si possible donne-nous un code complet (juste les parties nécessaires) mais qui est compilable et qui plante à l'exécution.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <unistd.h>
#include "struct.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <vector>
#include <typeinfo>
#include <cstdlib>
#include <ctime>
#include <signal.h>
#include <fcntl.h>


////////////////////////////////////////// DEFINES //////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////// GLOBAL VARIABLES //////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

vector<MiniControl*> vectMiniControl;
vector<int> vectPid;

///////////////////////////////////////// FUNCTIONS /////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////

/**
* Fonction qui permet de sortir du processus en cours a l'aide de Ctrl+C
*/
void action(int sig){
signal(SIGINT, SIG_DFL);
}

void lireDuPipe(int i){
const char *nom;
int fd=open(nom, O_RDONLY);
int temps;
if(fd!=-1){
read(fd, &temps, sizeof(temps));
signal(SIGSTOP, SIG_DFL);
sleep(temps);
signal(SIGCONT, SIG_DFL);
}
else
cout<<"Tube non disponible en lecture";
close(fd);
}


int main (int argc, char *argv[]){

string s;
int nbTrainLu, nbStationLu;
ifstream fichier;
fichier.open(argv[1]);
MiniControl* miniControleur;
if(fichier.fail()){ /** verification de l'ouverture du fichier */
cout<<"Erreur de lecture du fichier"<<endl;
return -1;
}
char *nbStation, *nbTrain;
fichier>>s>>nbStationLu>>nbTrainLu;
while(!fichier.eof()){
miniControleur=new MiniControl;
int tempPid=fork();
if(tempPid==-1){
perror("fork");
exit(1);
}
miniControleur->PID_=tempPid;
nbStation= new char;
nbTrain= new char;
sprintf(nbStation, "%d", nbStationLu);
sprintf(nbTrain, "%d", nbTrainLu);
if(miniControleur->PID_==0){
execlp("./mini-controleur", s.c_str(), nbStation, nbTrain, NULL);
cout<<"je suis le fils"<<endl;
}
else if(miniControleur->PID_!=0) cout<<"je suis le pere"<<endl;
miniControleur->nom_=s;/*********************/
cout<<miniControleur->nom_<<endl;
miniControleur->nbStation_=nbStationLu;
miniControleur->nbTrain_=nbTrainLu;
vectMiniControl.push_back(miniControleur);
vectPid.push_back(miniControleur->PID_);
int n=mkfifo(miniControleur->nom_.c_str(), 0777);
if(n==0)
cout<<"ca marche"<<endl;
else if(n==-1)
cout<<"ca marche pas"<<endl;
fichier>>s>>nbStationLu>>nbTrainLu;
}
for(int i=0;i<vectPid.size();i++){
// cout<<vectPid[i]<<endl;
}
for(int i=0;i<vectMiniControl.size();i++){
cout<<i<<" : "<<vectMiniControl[i]->nom_<<endl;
}

srand((unsigned)time(NULL));
int ligne, secondes;
srand((unsigned)time(NULL));
ligne=(int)rand()%vectMiniControl.size(); //generer un nombre aleatoire compri entre 0 et le nombre de mini-controleurs
cout<<ligne<<endl;
secondes=((int)rand()%(MAX_WAIT-MIN_WAIT))+MIN_WAIT; //generer un nombre aleatoire compri entre MIN_WAIT et MAX_WAIT
// cout<<"Suspendu pour "<<secondes<<" secondes"<<endl;
// signal(SIGSTOP, SIG_DFL); // attendre suspendre le processus pendant un certain temps, en utilisant les gestionnaires
// sleep(secondes); // par defaut des signaux SIGSTOP ET SIGCONT
// signal(SIGCONT, SIG_DFL);

srand((unsigned)time(NULL));
secondes=(int)rand()%(MAX_WAIT-MIN_WAIT);

int fd;
cout<<"NOM CHOISI: "<<vectMiniControl[ligne]->nom_<<endl;
fd=open(vectMiniControl[ligne]->nom_.c_str(), O_WRONLY);
cout<<"**************oooopen fini"<<endl;
// cout<<fd<<endl;
if(fd!=-1){
cout<<"ouverture reussie"<<endl;
write(fd, &secondes,sizeof(secondes));
}
else{
cout<<"Desole, tube non disponible"<<endl;
return -1;
}
close(fd);

return 0;
}

voici le code complet de controleur.cpp (compilable) et voila le fichier sim.txt dont il faut passer le nom comme argument lors de l'execution:

bleue 10 3
verte 12 4
orange 12 4

pour executer: bash> ./controleur sim.txt
Je te remercie vraiment beaucoup pour ton aide.
0
J'avais dit compilable -> 'struct.h' n'est pas trouvé!
J'avais dit juste les parties nécessaires, je ne pensais pas que le programme était aussi long; quand on a un problème dont on arrive pas à trouver l'erreur, il faut simplifier le programme au maximum.
J'ai omis de dire d'utiliser les balises '<code></code' (dans l'ordre: gras, italique, souligné, code, lien).
Si tu n'as pas plus simple à proposer, ça risque d'être long...
0
Oui, il faut vraiment simplifier.
- supprimer la classe 'MiniControl',
- ne pas utiliser le fichier 'sim.txt', mais envoyer une ligne de texte donnée,
- donner à 'secondes' une valeur fixe,
- envoyer la commande './mini-controleur' à la main,
On peut aussi diminuer la longueur du code, par exemple:
	cout << "**************oooopen fini" << endl;
	if(fd!= -1)
	{
		cout << "ouverture reussie" << endl;
		write(fd, &secondes,sizeof(secondes));
	}
	else
	{
		cout << "Desole, tube non disponible" << endl;
		return -1;
	}
par
	cout << "fd = " << fd << endl;
	if (fd == -1)
		return -1;
	write(fd, &secondes,sizeof(secondes));
0
ok alor depuis le debut:
controleur.cpp:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <vector>
#include <typeinfo>
#include <signal.h>
#include <fcntl.h>

vector<MiniControl*> vectMiniControl;
vector<int> vectPid;

struct MiniControl{
int PID_;
string nom_;
};

int main (int argc, char *argv[]){

	string s;
	int nbTrainLu, nbStationLu;
	ifstream fichier;
	fichier.open(argv[1]);
	MiniControl* miniControleur;
	char *nbStation, *nbTrain;
	fichier>>s;
	while(!fichier.eof()){
		miniControleur=new MiniControl;
		int tempPid=fork();
		if(tempPid==-1){
			perror("fork");
			exit(1);
		}
		miniControleur->PID_=tempPid;
		if(miniControleur->PID_==0){
			execlp("./mini-controleur", NULL);
		}

		miniControleur->nom_=s;
		vectMiniControl.push_back(miniControleur);
		int n=mkfifo(miniControleur->nom_.c_str(), 0777);
		if(n==0)
			cout<<"ca marche"<<endl;
		else if(n==-1)
			cout<<"ca marche pas"<<endl;
		fichier>>s;
	}

                int fd;
	cout<<"NOM CHOISI: "<<vectMiniControl[ligne]->nom_<<endl;
	fd=open(vectMiniControl[ligne]->nom_.c_str(), O_WRONLY);
	if(fd!=-1){
		cout<<"ouverture reussie"<<endl;
		write(fd, &secondes,sizeof(secondes));
	}
	else{
		cout<<"Desole, tube non disponible"<<endl;
		return -1;
	}
	close(fd);

	return 0;
}


et le contenu de sim.txt:
bleue
verte
orange

Voila j'ai essaye de simplifier le plus possible.
Merci.
0
Oui c est vrai j ai meme pas fait attention a ca.
Un tres gros merci vraiment.
0