web-dev-qa-db-fra.com

Comment envoyer une chaîne simple entre deux programmes utilisant des pipes?

J'ai essayé de chercher sur le net, mais il n'y a presque pas de ressources. Un petit exemple suffirait.

EDIT Je veux dire, deux programmes C différents communiquant l'un avec l'autre. Un programme doit envoyer "Salut" et l'autre doit le recevoir. Quelque chose comme ca.

104
user244333

Un tuyau normal ne peut connecter que deux processus liés. Il est créé par un processus et disparaîtra à la fermeture du dernier processus.

Un tube nommé , également appelé FIFO pour son comportement, peut être utilisé pour connecter deux non liés processus et existe indépendamment des processus; ce qui signifie qu'il peut exister même si personne ne l'utilise. Un FIFO est créé à l'aide de la fonction de bibliothèque mkfifo() .

Exemple

writer.c

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";

    /* create the FIFO (named pipe) */
    mkfifo(myfifo, 0666);

    /* write "Hi" to the FIFO */
    fd = open(myfifo, O_WRONLY);
    write(fd, "Hi", sizeof("Hi"));
    close(fd);

    /* remove the FIFO */
    unlink(myfifo);

    return 0;
}

reader.c

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#define MAX_BUF 1024

int main()
{
    int fd;
    char * myfifo = "/tmp/myfifo";
    char buf[MAX_BUF];

    /* open, read, and display the message from the FIFO */
    fd = open(myfifo, O_RDONLY);
    read(fd, buf, MAX_BUF);
    printf("Received: %s\n", buf);
    close(fd);

    return 0;
}

Remarque: La vérification d'erreur a été omise du code ci-dessus pour des raisons de simplicité.

150
jschmier

À partir de Création de canaux dans C , cela vous montre comment créer un programme pour utiliser un canal. Si vous ne voulez pas fork (), vous pouvez utiliser tubes nommés .

De plus, vous pouvez obtenir l'effet de prog1 | prog2 en envoyant la sortie de prog1 à la sortie standard et en lisant stdin dans prog2. Vous pouvez également lire stdin en ouvrant un fichier nommé /dev/stdin (mais sans être sûr de sa portabilité).

/*****************************************************************************
 Excerpt from "Linux Programmer's Guide - Chapter 6"
 (C)opyright 1994-1995, Scott Burkett
 ***************************************************************************** 
 MODULE: pipe.c
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
                exit(0);
        }
        else
        {
                /* Parent process closes up output side of pipe */
                close(fd[1]);

                /* Read in a string from the pipe */
                nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                printf("Received string: %s", readbuffer);
        }

        return(0);
}
40
Stephen
dup2( STDIN_FILENO, newfd )

Et lis:

char reading[ 1025 ];
int fdin = 0, r_control;
if( dup2( STDIN_FILENO, fdin ) < 0 ){
    perror( "dup2(  )" );
    exit( errno );
}
memset( reading, '\0', 1025 );
while( ( r_control = read( fdin, reading, 1024 ) ) > 0 ){
    printf( "<%s>", reading );
    memset( reading, '\0', 1025 );
}
if( r_control < 0 )
    perror( "read(  )" );    
close( fdin );    

Mais, je pense que fcntl peut être une meilleure solution

echo "salut" | code
8
mlouk

Ce qu'un programme écrit sur stdout peut être lu par un autre via stdin. Donc, simplement, en utilisant c, écrivez prog1 pour imprimer quelque chose en utilisant printf() et prog2 pour lire quelque chose en utilisant scanf(). Alors viens courir

./prog1 | ./prog2
6
Johan

Voici un exemple :

int main()
{
    char buff[1024] = {0};
    FILE* cvt;
    int status;
    /* Launch converter and open a pipe through which the parent will write to it */
    cvt = popen("converter", "w");
    if (!cvt)
    {
        printf("couldn't open a pipe; quitting\n");
        exit(1)
    }
    printf("enter Fahrenheit degrees: " );
    fgets(buff, sizeof (buff), stdin); /*read user's input */
    /* Send expression to converter for evaluation */
    fprintf(cvt, "%s\n", buff);
    fflush(cvt);
    /* Close pipe to converter and wait for it to exit */
    status=pclose(cvt);
    /* Check the exit status of pclose() */
    if (!WIFEXITED(status))
        printf("error on closing the pipe\n");
    return 0;
}

Les étapes importantes de ce programme sont les suivantes:

  1. L'appel popen() qui établit l'association entre un processus enfant et un canal dans le parent.
  2. L'appel fprintf() qui utilise le canal comme un fichier ordinaire pour écrire dans le stdin du processus enfant ou pour le lire à partir de sa sortie standard.
  3. L'appel pclose() qui ferme le canal et provoque la fin du processus enfant.
4
Preet Sangha

tout d’abord, demandez au programme 1 d’écrire la chaîne sur stdout (comme si vous souhaitiez qu’elle apparaisse à l’écran). le second programme doit alors lire une chaîne à partir de stdin, comme si un utilisateur tapait à partir du clavier. alors tu cours:

programme_1 | programme_2

2
lfagundes

Cette réponse pourrait être utile pour un futur Googler.

#include <stdio.h>
#include <unistd.h>

int main(){     
     int p, f;  
     int rw_setup[2];   
     char message[20];      
     p = pipe(rw_setup);    
     if(p < 0){         
        printf("An error occured. Could not create the pipe.");  
        _exit(1);   
     }      
     f = fork();    
     if(f > 0){
        write(rw_setup[1], "Hi from Parent", 15);    
     }  
     else if(f == 0){       
        read(rw_setup[0],message,15);       
        printf("%s %d\n", message, r_return);   
     }  
     else{      
        printf("Could not create the child process");   
     }      
     return 0;

}

Vous pouvez trouver un exemple d'appel de canal bidirectionnel avancé ici .

1
Anjana