Bagaimana cara mengirim string sederhana antara dua program menggunakan pipa?


111

Saya mencoba mencari di internet, tetapi hampir tidak ada sumber daya. Contoh kecil sudah cukup.

EDIT Maksud saya, dua program C yang berbeda berkomunikasi satu sama lain. Satu program harus mengirimkan "Hai" dan yang lainnya akan menerimanya. Sesuatu seperti itu.

c  unix  pipe 

1
Mungkin maksud Anda tidak seperti itu ls | grep ".o"? Mungkin penjelasan lebih lanjut tentang apa yang Anda maksud akan membantu ...
Jerry Coffin

13
Ayolah ... sedikit usaha. Google "kode contoh pipa c". Hasil pertama tepat: tldp.org/LDP/lpg/node11.html
Stephen

4
Saya ingin komunikasi antara dua program yang sama sekali berbeda. Saya tidak dapat menemukan sumber daya untuk itu.

1
Jika Anda tidak melakukan forking, maka Anda perlu melihat "pipa bernama".
Hakim Maygarden

Jawaban:


156

Pipa biasa hanya dapat menghubungkan dua proses terkait. Itu dibuat oleh suatu proses dan akan hilang ketika proses terakhir menutupnya.

Sebuah pipa bernama , juga disebut FIFO untuk perilakunya, dapat digunakan untuk menghubungkan dua proses yang tidak berhubungan dan ada secara independen dari proses; artinya itu bisa ada bahkan jika tidak ada yang menggunakannya. FIFO dibuat menggunakan mkfifo()fungsi perpustakaan.

Contoh

penulis. 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;
}

pembaca.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;
}

Catatan: Pemeriksaan kesalahan dihilangkan dari kode di atas untuk kesederhanaan.


6
Apa yang dianggap proses terkait ?
Pithikos

7
Mungkin proses yang terkait melalui satu atau lebih relasi orang tua / anak (misalnya termasuk saudara kandung). Nenek moyang yang sama akan menciptakan kedua ujung pipa tersebut. Proses yang tidak terkait tidak memiliki leluhur yang sama.
MSalters

4
Ini tidak akan berhasil jika pembaca memulai lebih dulu. Perbaikan cepat adalah dengan menempatkan open()pembaca di dalam lingkaran. Namun +1 karena Anda memberikan contoh dua program.
gsamaras

Saya mengambil contoh ini perlu beberapa tweaker untuk bekerja pada windows? unistd.h menjadi POSIX dan semua ...
David Karlsson

Ya, itu perlu tweaker untuk Windows. The artikel Wikipedia pada pipa bernama membahas beberapa perbedaan Unix / Windows dan cepat pencarian Google dapat membantu dengan pelaksanaan Windows.
jschmier

41

Dari Membuat Pipa di C , ini menunjukkan kepada Anda bagaimana membuat program untuk menggunakan pipa. Jika Anda tidak ingin melakukan fork (), Anda bisa menggunakan pipa bernama .

Selain itu, Anda bisa mendapatkan efek prog1 | prog2dengan mengirimkan output prog1ke stdout dan membaca dari stdindalam prog2. Anda juga dapat membaca stdin dengan membuka file bernama /dev/stdin(tapi tidak yakin portabilitasnya).

/*****************************************************************************
 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);
}

1
Hai Stephen, bagaimanapun saya bisa menggunakan kode ini untuk dua fungsi yang berbeda? Arti menulis ke pipa dilakukan di satu fungsi dan membaca pipa di fungsi lain ?? kode yang berfungsi seperti ini akan dihargai.
Mohsin

8
dup2( STDIN_FILENO, newfd )

Dan baca:

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 );    

Tapi, saya pikir itu fcntlbisa menjadi solusi yang lebih baik

echo "salut" | code

6

Apa yang ditulis satu program ke stdout dapat dibaca oleh program lain melalui stdin. Jadi sederhananya, menggunakan c, tulis prog1untuk mencetak sesuatu menggunakan printf()dan prog2membaca sesuatu menggunakan scanf(). Lalu lari saja

./prog1 | ./prog2

4

Berikut contohnya :

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;
}

Langkah-langkah penting dalam program ini adalah:

  1. The popen()panggilan yang menetapkan hubungan antara proses anak dan pipa di orangtua.
  2. Itu fprintf() panggilan yang menggunakan pipa sebagai file biasa untuk menulis ke stdin proses anak atau membaca dari stdout.
  3. The pclose()panggilan yang menutup pipa dan menyebabkan proses anak untuk mengakhiri.

Saya pikir contoh ini meleset dari inti pertanyaannya, meskipun saya mengakui bahwa program "konverter" adalah program yang berbeda. Komentar pertama membahas komunikasi antara program yang sepenuhnya independen yang tidak memiliki hubungan saudara / orang tua / sepupu kedua.
cmm

2

Pertama, minta program 1 untuk menulis string stdout(seolah-olah Anda ingin muncul di layar). Kemudian program kedua harus membaca string dari stdin, seolah-olah pengguna sedang mengetik dari keyboard. lalu kamu lari:

$ program_1 | program_2

1

Jawaban ini mungkin berguna untuk karyawan Google di masa mendatang.

#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;

}

Anda dapat menemukan contoh panggilan pipa dua arah lanjutan di sini .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.