Jak wysłać prosty ciąg między dwoma programami za pomocą potoków?
111
Próbowałem szukać w sieci, ale prawie nie ma żadnych zasobów. Wystarczyłby mały przykład.
EDYCJA Mam na myśli dwa różne programy w C komunikujące się ze sobą. Jeden program powinien wysłać „Cześć”, a drugi powinien je odebrać. Coś w tym stylu.
Prawdopodobnie nie masz na myśli czegoś takiego ls | grep ".o"? Być może trochę więcej wyjaśnienia tego, co masz na myśli, pomogłoby ...
Jerry Coffin
13
Chodź stary ... trochę wysiłku. Google „c pipe przykład kod”. Pierwszy wynik jest dokładny: tldp.org/LDP/lpg/node11.html
Stephen
4
Chcę komunikacji między dwoma zupełnie różnymi programami. Nie mogłem znaleźć odpowiedniego źródła.
1
Jeśli nie rozwidlasz procesu, musisz spojrzeć na „nazwane potoki”.
Sędzia Maygarden
Odpowiedzi:
156
Zwykły potok może łączyć tylko dwa powiązane procesy. Jest tworzony przez proces i zniknie, gdy ostatni proces go zamknie.
Nazwie rura , zwana także FIFO jego zachowania może być stosowany do łączenia dwóch niepowiązanych procesów i występuje niezależnie od procesów; co oznacza, że może istnieć, nawet jeśli nikt go nie używa. FIFO jest tworzone za pomocą mkfifo()funkcji biblioteki.
Przykład
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);return0;}
czytelnik c
#include<fcntl.h>#include<stdio.h>#include<sys/stat.h>#include<unistd.h>#define MAX_BUF 1024int 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);return0;}
Uwaga: sprawdzanie błędów zostało pominięte w powyższym kodzie dla uproszczenia.
Prawdopodobnie procesy, które są powiązane przez jedną lub więcej relacji rodzic / dziecko (np. Obejmuje rodzeństwo). Wspólny przodek stworzyłby dwa końce rury. Niepowiązane procesy nie mają tego wspólnego przodka.
MSalters
4
To nie zadziała, jeśli czytnik uruchomi się pierwszy. Szybkim rozwiązaniem byłoby umieszczenie open()czytnika w pętli. Jednak +1, ponieważ podajesz przykład dwóch programów.
gsamaras
Rozumiem, że ten przykład wymaga pewnych poprawek, aby działać w systemie Windows? unistd.h jest POSIX i wszystko ...
Ponadto, można uzyskać efekt prog1 | prog2wysyłając wyjście prog1do stdout i odczyt z stdinw prog2. Możesz również odczytać stdin, otwierając plik o nazwie /dev/stdin(ale nie jesteś pewien, czy można go przenosić).
/*****************************************************************************
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);}
Hej Stephen, w każdym razie mogę użyć tego kodu do dwóch różnych funkcji? czyli pisanie do potoku odbywa się w jednej funkcji, a odczytywanie potoku w innej funkcji? taki działający kod byłby mile widziany.
To, co jeden program zapisuje na standardowe wyjście, może zostać odczytane przez inny program poprzez stdin. Więc po prostu, używając c, napisz, prog1aby wydrukować coś za pomocą printf()i prog2przeczytać coś za pomocą scanf(). Potem po prostu biegnij
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");return0;}
Ważne kroki w tym programie to:
popen()Połączenia, które ustala związek między proces potomny i rury w rodzica.
fprintf()Wezwanie, które wykorzystuje rurę jako zwykły plik napisać do stdin procesu potomnego lub odczytać z jego standardowe wyjście.
pclose()Połączenia, które zamyka rurę i powoduje, że proces potomnego.
Myślę, że ten przykład mija się z celem pytania, chociaż przyznaję, że program „konwerter” to inny program. Pierwszy komentarz dotyczy komunikacji między całkowicie niezależnymi programami, które nie mają relacji rodzeństwo / rodzic / drugi kuzyn.
cmm
2
Najpierw stdoutniech program 1 zapisze łańcuch do (tak jakbyś chciał, żeby pojawił się na ekranie). Następnie drugi program powinien odczytać ciąg znaków stdin, tak jakby użytkownik pisał z klawiatury. wtedy biegniesz:
Ta odpowiedź może być pomocna dla przyszłego pracownika Google.
#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);}elseif(f ==0){
read(rw_setup[0],message,15);
printf("%s %d\n", message, r_return);}else{
printf("Could not create the child process");}return0;}
Można znaleźć zaawansowaną dwukierunkową przykład połączenia rura tutaj .
ls | grep ".o"
? Być może trochę więcej wyjaśnienia tego, co masz na myśli, pomogłoby ...Odpowiedzi:
Zwykły potok może łączyć tylko dwa powiązane procesy. Jest tworzony przez proces i zniknie, gdy ostatni proces go zamknie.
Nazwie rura , zwana także FIFO jego zachowania może być stosowany do łączenia dwóch niepowiązanych procesów i występuje niezależnie od procesów; co oznacza, że może istnieć, nawet jeśli nikt go nie używa. FIFO jest tworzone za pomocą
mkfifo()
funkcji biblioteki.Przykład
writer.c
czytelnik c
Uwaga: sprawdzanie błędów zostało pominięte w powyższym kodzie dla uproszczenia.
źródło
open()
czytnika w pętli. Jednak +1, ponieważ podajesz przykład dwóch programów.Z tworzenia potoków w C , to pokazuje, jak rozwidlić program, aby używał potoku. Jeśli nie chcesz rozwidlać (), możesz użyć nazwanych potoków .
Ponadto, można uzyskać efekt
prog1 | prog2
wysyłając wyjścieprog1
do stdout i odczyt zstdin
wprog2
. Możesz również odczytać stdin, otwierając plik o nazwie/dev/stdin
(ale nie jesteś pewien, czy można go przenosić).źródło
I czytać:
Ale myślę, że to
fcntl
może być lepsze rozwiązanieźródło
To, co jeden program zapisuje na standardowe wyjście, może zostać odczytane przez inny program poprzez stdin. Więc po prostu, używając c, napisz,
prog1
aby wydrukować coś za pomocąprintf()
iprog2
przeczytać coś za pomocąscanf()
. Potem po prostu biegnijźródło
Oto próbka :
Ważne kroki w tym programie to:
popen()
Połączenia, które ustala związek między proces potomny i rury w rodzica.fprintf()
Wezwanie, które wykorzystuje rurę jako zwykły plik napisać do stdin procesu potomnego lub odczytać z jego standardowe wyjście.pclose()
Połączenia, które zamyka rurę i powoduje, że proces potomnego.źródło
Najpierw
stdout
niech program 1 zapisze łańcuch do (tak jakbyś chciał, żeby pojawił się na ekranie). Następnie drugi program powinien odczytać ciąg znakówstdin
, tak jakby użytkownik pisał z klawiatury. wtedy biegniesz:źródło
Ta odpowiedź może być pomocna dla przyszłego pracownika Google.
Można znaleźć zaawansowaną dwukierunkową przykład połączenia rura tutaj .
źródło