42toto42 Posté(e) le 5 mars 2007 Partager Posté(e) le 5 mars 2007 bonsoir j'ai un code, et je ne comprends pas bien comment il tourne, peut-on m'expliquer ? ce programme s'exectue en prennant un parametre, il est sence creer un tuyau entre deux commandes rentrees en dur, apres, j'en sais pas plus... j'ai compris comment marche pipe(), je pense comprendre comment marche dup, mais pourquoi quand je le lance avec a, il me fait un ls -lR | more et quand je le lance avec b, il me fait la meme commande avec un broken pipe en prime. j'ai rajoute des write au milieu, et on note qu'avec l'option a, il passe d'abord dans le else et revient dans le if, et avec la b, on fait le if puis le else; c'est la que je me dis que quelques notions elementaires de programmation m'ont echappees en gros, comment le programme fait pour passer a la fois dans le if et dans le else, et surtout dans le else avant le if ??? comment marche le dup exactement ? ou lis-t-on, ou ecris-t-on ? excusez moi de vous en demander tant et merci pour votre aide #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char **argv) { int p[2]; int pid; if (argc != 2) { printf("usage: ./a.out a or ./a.out b\n"); exit(1); } if (pipe(p) < 0) printf("pipe error\n"); if ((pid = fork()) < 0) printf("fork error\n"); if (!strcmp(argv[1], "a") && pid == 0 || !strcmp(argv[1], "b") && pid) { write(1, "OK\n", 3); close(p[0]); dup2(p[1], 1); execlp("ls", "ls", "-lR", "/w/dev", 0); printf("execl\n"); } else { write(1, "KO\n", 3); close(p[1]); dup2(p[0], 0); execlp("more", "more", 0); printf("execl\n"); } } edit: excusez moi, je n'avais pas vu qu'il y avait une section code... je ne trouve pas ou supprimer le sujet. enfin, pour eviter les double post, on attendra le passage d'un admin. encore desole Lien vers le commentaire Partager sur d’autres sites More sharing options...
tuXXX Posté(e) le 6 mars 2007 Partager Posté(e) le 6 mars 2007 Je déplace Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 6 mars 2007 Partager Posté(e) le 6 mars 2007 mhmmm, c'est assez classique. Quand tu appelle fork(), tu créés dupliques ton processus. Tu te retrouves donc avec un processus père et un processus fils. Le test if(pid == 0) ... else sert donc à savoir si tu es dans le processus père ou dans le processus fils. Puisque tu as un père et un fils, les deux branches du test vont effectivement s'éxécuter, seulement la première partie (pid == 0) est exécutée par le fils, alors que la seconde (pid > 0) le sera par le père. Dans ton cas, tu bidouilles pour t'arranger à ce que si on passe comme argument 'a', ce soit le père qui fasse le "ls" et le fils le "more", alors que si on entre 'b', ce sera l'inverse. (c'est tordu, mais ça se lit quand même). Le gros problème que tu as, c'est que l'ordonnancement sur un système UNIX n'est pas temps réel : tu n'as aucun moyen de savoir quel processus entre le père et le fils va s'exécuter en premier. Il est donc tout à fait normal que des fois le if se fasse avant le else et des fois non. C'est le hasard (en tout cas, c'est non prédictible et non reproductible). la fonction dup2() sert juste à attribuer un numéro particulier à un descripteur de fichier . Petit extrait du man : dup() et dup2() créent une copie du descripteur de fichier oldfd.Après un appel réussi à dup() ou dup2(), l'ancien et le nouveau descripteurs peuvent être utilisés de manière interchangeable. ... dup2() transforme newfd en une copie de oldfd, fermant auparavant newfd si besoin est. dans ton cas, tu t'en sers pour faire pointer les entrées/sorties standards (0 et 1) vers ton pipe. voilà Lien vers le commentaire Partager sur d’autres sites More sharing options...
42toto42 Posté(e) le 6 mars 2007 Auteur Partager Posté(e) le 6 mars 2007 ok merci mais sur le man de dup2, il y a marque que dup2 ferme newfd si besoin est... c'est pas une connerie de s'ammuser a close les fd 0, 1 ou 2 ??? Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 6 mars 2007 Partager Posté(e) le 6 mars 2007 non, il ne sera fermé que pour le processus appelant dup2(). Lien vers le commentaire Partager sur d’autres sites More sharing options...
42toto42 Posté(e) le 12 mars 2007 Auteur Partager Posté(e) le 12 mars 2007 merci pour ton aide, mais maintenant que j'ai compris le principe, je me suis lance dans des fonctions qui me permettraient d'effectuer des pipe en boucle, et j'ai un petit soucis tout se base sur une liste chainee qui, sur chaque maillon, me garde en memoire la commande (/bin/ls), les arguments (ls -lah), le symbole precedant et le suivant (genre pipes, point virgule, etc.). Cette liste chainee, c'est t_act, la commande est le char *cmd, les arguments sont char **parsd, les symboles sont beg et nex. A partir de la, je balance ma liste dans la fonction expipe(cf bout de code ci-dessous), qui va appeller reqpipe, sence s'appeller en boucle jusqu'a ce qu'on soit arrive au dernier pipe. a priori, ca marche, ca compile, ca segfault pas, tout va tres bien, mais il me reste quand meme un probleme: cette fonction n'est qu'une infime partie d'un programme, mais une fois appellee, le programme quitte..... (sans erreures, ni rien, gdb me dit Program exited normally) int reqpipe(t_act *a, char **e, int fdsp[2]) { int fds[2]; int pid; int x; if (a->nex != 2) { close(fdsp[1]); dup2(fdsp[0], 0); a->ok = 1; x = xexecve(a->cmd, a->parsd, e); } else { close(fdsp[1]); dup2(fdsp[0], 0); if ((pipe(fds)) < 0) warning(PIPEERR); else if ((pid = fork()) == -1) warning(FORKERR); else if (!pid) { close(fds[0]); dup2(fds[1], 1); x = xexecve(a->cmd, a->parsd, e); } else fds[0] = reqpipe(a->next, e, fds); if (!x) a->ok = -1; return (fds[0]); } if (!x) a->ok = -1; return (fdsp[0]); } int expipe(t_act *a, char **e) { int fds[2]; int pid; int x; if ((pipe(fds)) < 0) warning(PIPEERR); else if ((pid = fork()) == -1) warning(FORKERR); if (!pid) { close(fds[0]); dup2(fds[1], 1); a->ok = 1; x = xexecve(a->cmd, a->parsd, e); } else fds[0] = reqpipe(a->next, e, fds); close(fd); if (x) return (1); a->ok = -1; return (0); } Lien vers le commentaire Partager sur d’autres sites More sharing options...
Messages recommandés
Archivé
Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.