Aller au contenu

pipe() && dup2()


Messages recommandés

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

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à :ouioui:

Lien vers le commentaire
Partager sur d’autres sites

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

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...