cas d'école : réécriture des pipes bash : chui pas loin... [C] - C - Programmation
Marsh Posté le 28-03-2005 à 13:47:41
brisssou a écrit : allé, vous qui l'avez lu, z'avez pas une idée ? |
Putain si tu mettais des commentaires et si tu indentais un peu ça irait quand-même beaucoup mieux pour tout le monde !!!
Dejà les trucs bateaux:
1) Pourquoi tu limites "param" à 8 ?
2) A quoi sert "ppid" ?
Remarque je m'en fous et c'est pas important mais la question peut se poser...
Sinon je comprends pas trop ta logique. Pourquoi fermer les deux cotés du tube ? Pourquoi dupliquer dans certains cas l'entrée standard ou la sortie standard dans un autre cas. Commente un peu tes idées !!!
Petite remarque en passant: while (i<argc) au tout début te donne une boucle infinie si "i" n'est jamais incrémenté. Or, "i" ne s'incrémente que si argv[i] = "-m". C'est toujours le cas ? Il y a peut-être là une idée à creuser quand tu dis que ton programme ne s'arrête jamais...
PS: J'aime bien ta gestion des erreurs. Moi, je ne suis jamais allé aussi loin. Quand j'ai une erreur, j'affiche printf("%s\n", strerror(errno)) et basta.
Marsh Posté le 28-03-2005 à 13:53:09
Sve@r a écrit : PS: J'aime bien ta gestion des erreurs. Moi, je ne suis jamais allé aussi loin. Quand j'ai une erreur, j'affiche printf("%s\n", strerror(errno)) et basta. |
Et moi
perror("" ); |
Marsh Posté le 28-03-2005 à 14:00:18
Emmanuel Delahaye a écrit : Et moi
|
En fait, j'affiche plus de trucs dont, entre autres, "__LINE__" et "__FILE__" donc pour moi, "perror()" ne m'est pas utile Mais tout ça ne fait pas avancer le schmiliblik...
Marsh Posté le 28-03-2005 à 17:52:30
Sve@r a écrit : Putain si tu mettais des commentaires et si tu indentais un peu ça irait quand-même beaucoup mieux pour tout le monde !!! |
pour l'indentation, bha c'est déjà bon là je crois, c'est mon code copié/coller depuis Eclipse :-/
la limite à 8 est arbitraire... 2 ou 15, spareil pour moi...
ppid ne sert à rien, bien observé. merci.
Pour les commentaires, ok j'en rajoute un peu... voir le premier message, il est édité.
la fermeture des tubes, j'ai pas compris... j'ai copié ça sur d'autres listing où les tubes se fermaient, et d'un coup, ça a mieux marché chez moi... comment ça je tatonne ?!
la boucle possiblement infinie, c'est bien vu aussi... je vais voir si je peux corriger ça...
mais ce n'est pas ça qui faisait planter à priori, parce que le processeur n'est pas pris à 100% (indication de 'top')
merci en tout cas !
Marsh Posté le 28-03-2005 à 19:19:51
brisssou a écrit : pour l'indentation, bha c'est déjà bon là je crois, c'est mon code copié/coller depuis Eclipse :-/ |
Excellent ! Avec tes commentaires au-moins 1) j'ai beaucoup ri 2) je comprends mieux ta logique qui est la suivante => j'y comprends rien mais jm'en fous je m'avance bravement
A mon avis, ton problème vient de tes tubes (hum... je m'avance pas beaucoup) mais je crois que je peux t'aider à t'en sortir. Faut juste que tu comprennes bien comment fonctionne les tubes inter-process
Un tube est un canal qui permet de faire dialoguer deux processus. Quand les processus sont liés par un "fork", on peut utiliser des tubes mémoires avec la fonction "int pipe(int cote[2]);".
Cette fonction t'ouvre un canal où les entrées/sorties sont représentées par "cote[0]" (sortie) et "cote[1]" (entrée).
Pourquoi on ferme les cotés ? En général, quand on fait communiquer un père et son fils, l'un écrit et l'autre lit. Donc le programme commence par ouvrir le tube puis génère le fils. Ensuite, comme les deux processus ont hérité chacun des deux cotés du tube mais que chacun n'en a besoin que d'un, ben il ferme l'autre. Toi, tu fermes allègrement les deux dans le fils et aucun dans le père.
De plus, quand tu fais "dup2(tube[0], STDIN_FILENO) alors tu rediriges la sortie du tube vers le clavier alors qu'à mon avis, il faudrait rediriger le clavier dans l'entrée => dup2(STDIN_FILENO, tube[1]) mais je crois que le problème est quand-même un peu plus complexe (c'est d'ailleurs la première fois que je suis confronté à ça et je galère un peu à trouver l'idée)
Je crois qu'il faut que tu commences par le dernier programme et que tu remontes vers le premier. En effet, si quand tu lances "prog -m ls -m more" tu lances le "ls" en premier, ben le "ls" se déroulera connement et n'ira jamais dans le more. Alors que si tu lances le "more" en premier, ben il attendra sagement que des données lui arrivent. Evidemment, ta boucle sera moins évidente à programmer mais tu peux t'en sortir si tu commences par récupérer la liste de tous tes programmes dans un tableau. T'auras plus qu'à balayer ton tableau à l'envers.
En plus, comme t'as "n" programmes il te faut "n - 1" tubes donc le coup des tableaux c'est pas mal parce que tu peux allouer (malloc) et ouvrir (pipe) d'un coup tes "n - 1" tubes
Voilà ce que je propose pour ton programme
- Il stocke tous les processus à lancer et crée tous les tubes
- Il génère un fils pour chaque processus en commençant par le dernier
- Il ferme tous les tubes car il ne s'en sert pas
Le premier fils généré
- Il redirige STDIN_FILENO vers le cote[1] (entrée) de son propre tube
Chaque fils (même le premier mais pas le dernier)
- Il redirige le cote[0] (sortie) de son propre tube vers le cote[1] (entrée) du tube suivant
Le dernier fils
- Il redirige le cote[0] (sortie) de son propre tube vers STDOUT_FILENO
Tous les fils doivent, en plus, fermer les cotés de tous les tubes qu'ils n'utilisent pas. Putain, c'est pas facile à imaginer. Et je suis même pas certain que ce soit nickel. Mais c'est mon idée.
Marsh Posté le 28-03-2005 à 19:26:41
wow !
je regarde tout ça, merci en tout cas...
mais quand même, je comprends pas pourquoi ça marche un peu mon code...
et puis, j'ai fait un petit top --forest, ça me donne ça :
Code :
|
et ça me donne ça quand ça bloque, donc en fait, c'est que grep ne fini pas...
Marsh Posté le 28-03-2005 à 21:11:23
brisssou a écrit : wow !
|
Vi, le grep ne finit pas parce qu'il n'a aucune donnée à traiter.
Il se comporte comme si tu tapais la commande "grep obje" sans lui dire où chercher. Le grep cherche dans l'entrée standard...
Déjà, un premier exercice devrais t'aider :
Un père et deux fils avec le père qui envoie des données au premier fils qui les envoie au second...
Marsh Posté le 29-03-2005 à 02:42:45
brisssou a écrit : mais pourtant, si je met rien après le grep, il fonctionne. C'est là que je comprends pas en fait... |
Déjà, essaye juste avec 3 programmes en dur style "ls |sort |more".
Génère 3 fils et 2 tubes
Si ça marche, il te sera facile d'étendre à tous les programmes passés en paramètre.
Marsh Posté le 05-04-2005 à 15:07:45
Sve@r a écrit : Déjà, essaye juste avec 3 programmes en dur style "ls |sort |more". |
Ce petit TP m'a plu et je me suis amusé à le faire.
Voici le source n° 1 (les programmes sont lancés dans l'ordre demandé)
Code :
|
Voici le source n° 2 (les programmes sont lancés dans l'ordre inverse)
Code :
|
Les informations qu'affichent chacun de ces deux programmes sont affichées sur le canal "STDERR". On peut donc les shunter en redirigeant ce canal "2" vers "/dev/null".
En fait, qu'on lance les processus à l'endroit ou à l'envers, ça marche.
Marsh Posté le 27-03-2005 à 17:30:38
Chui pas loin, mais c'est pas ça...
donc en gros mon problème de cours (évidemment, c'est pas pour le plaisir...), c'ets de réécrire le fonctionnement des pipes uni (|) en C. En gros, il faudrait que
monProg -m /bin/ls -m /bin/cat
donne la même sortie que
/bin/ls | /bin/cat
(je vous prend pas pour des buses, je veux juste être clair).
Avec ce que j'ai déjà fait, ça marche avec une commande (cool), presque avec deux (pas mal) et pas du tout avec 3. Parce que avec 2, ça marche que presque, parce que le programme ne se fini pas, il ne retourne pas sous le shell, du coup, avec trois, ça ne passe jamais au troisième, ça bloque à la fin du deuxième...
Mon code n'est pas forcement clair, étant donné que le C, c'est pas mon point fort, je suis prèt pour les critiques.
La question : pourquoi ça bloque à après la deuxième mutation ?!
merci pour toute aide.
edit : ajouts des commentaires
Message édité par brisssou le 28-03-2005 à 18:00:13
---------------
HFR - Mes sujets pour Chrome - Firefox - vérifie les nouveaux posts des topics suivis/favoris