OVH Cloud OVH Cloud

Pipe bidirectionnel

15 réponses
Avatar
JKB
Bonjour à tous,

Petite question du soir... Je sèche lamentablement sur les pipes
bidirectionnels et sur ce coup, google n'a pas été mon ami...

J'ai un programme qui fait un fork, mais j'aimerais que le père puisse
écrire sur l'entrée standard du fils et récupérer ses sorties standard et
d'erreur.

Première question, la plus simple : est-ce que tous mes descripteurs sont
bien refermés ?

J'arrive très bien à récupérer stderr et stdout dans le père, mais lorsque
je tente d'écrire depuis le père, mon truc bloque (le processus détaché par
l'appel execvp du fils prend tout le CPU). Je sèche. Voici mon code :

int pipes[2];

...

if (pipe(pipes) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}

if ((pid = fork()) < 0)
{
/*
* Le fork échoue
*/

if (close(pipes[0]) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}

if (close(pipes[1]) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}

(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
else if (pid == 0)
{
#undef test
#define test
// En ôtant cette dernière ligne, on ne tient pas compte de stdin et
// ça fonctionne bien.
#ifndef test
if (close(pipes[0]) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
#else
if (pipes[0] != STDIN_FILENO)
{
if (dup2(pipes[0], STDIN_FILENO) == -1)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
}
#endif

if (pipes[1] != STDOUT_FILENO)
{
if (dup2(pipes[1], STDOUT_FILENO) == -1)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
}

if (pipes[1] != STDERR_FILENO)
{
if (dup2(pipes[1], STDERR_FILENO) == -1)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
}

if (nombre_arguments != 0)
{
execvp(arguments[0], arguments);
}
else
{
exit(EXIT_SUCCESS);
}

exit(EXIT_FAILURE);
}
else
{
#ifndef test
if (close(pipes[1]) != 0)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
#else
if (write(pipes[1], "1\n", 2) != 2)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}
#endif

if (waitpid(pid, &status, 0) == -1)
{
(*s_etat_processus).erreur_systeme = d_es_processus;
return;
}

longueur_lecture = 256;
pointeur = 0;
nombre_iterations = 1;

if ((tampon = malloc((longueur_lecture + 1) *
sizeof(unsigned char))) == NULL)
{
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
return;
}
...

Une idée ? Parce que franchement, je ne vois pas pourquoi cela ne fonctionne
pas...

Cordialement,

JKB

--
En plus c'est simple, je fais ce genre de trucs en g77 depuis des années :
il suffit d'écrire un wrapper en C. Et comme ça, j'ai le meilleur des deux
mondes : la rigueur quasi-monacale du Fortran, et l'exubérance pétulante du C.

5 réponses

1 2
Avatar
drkm
Eric Levenez writes:

Non, les pipes basés sur les STREAMS sont bidirectionnels.


C'est quoi, les pipes basés sur les STREAMS ?

--drkm

Avatar
Eric Levenez
Le 2/10/05 21:09, dans , « drkm »
a écrit :

Eric Levenez writes:

Non, les pipes basés sur les STREAMS sont bidirectionnels.


C'est quoi, les pipes basés sur les STREAMS ?


Les STREAMS sont une architecture logiciel introduite sous SVR3 pour faire
des modules dans le noyau. Ces modules ont une entrée et un sortie et font
un traitement donné. On peut dynamiquement empiler et dépiler des modules.
On a aussi des modules multiplexeurs. On peut par exemple avoir un module de
cryptage qu'un processus empile dynamiquement sur une pile TCP/IP. Les pipes
basées sur les STREAMS sont des pipes "normaux" mais ils sont basées sur
l'architecture STREAMS. Cela veut dire qu'en plus d'être bidirectionnels,
ces pipes peuvent aussi recevoir des modules que l'utilisateur empile à la
guise (cryptage, compression, traces...)

<http://cm.bell-labs.com/cm/cs/who/dmr/st.html>
<http://docsun.cites.uiuc.edu/sun_docs/C/solaris_9/SUNWdev/STREAMS/p17.html>

L'appel système pipe des unix utilisant les STREAMS est compatible ascendant
avec les unix utilisant les pipes monodirectionnels.

<http://uw713doc.caldera.com/en/man/html.2/pipe.2.html>

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.


Avatar
drkm
Eric Levenez writes:

Le 2/10/05 21:09, dans , « drkm »

C'est quoi, les pipes basés sur les STREAMS ?


Les STREAMS sont une architecture logiciel introduite sous SVR3 pour faire
des modules dans le noyau.

[...]


Très intéressant. Merci pour l'explication et les liens.

--drkm


Avatar
Laurent Wacrenier
JKB écrit:
Petite question du soir... Je sèche lamentablement sur les pipes
bidirectionnels et sur ce coup, google n'a pas été mon ami...


Pas standard. Utilise plutôt des socket (avec socketpair() au lieu de pipe()).

Avatar
JKB
Le 03-10-2005, à propos de
Re: Pipe bidirectionnel,
Laurent Wacrenier écrivait dans fr.comp.os.unix :
JKB écrit:
Petite question du soir... Je sèche lamentablement sur les pipes
bidirectionnels et sur ce coup, google n'a pas été mon ami...


Pas standard. Utilise plutôt des socket (avec socketpair() au lieu de pipe()).


J'ai résolu mon problème avec deux pipes.

Merci,

JKB


1 2