¿Cómo enviar una cadena simple entre dos programas usando tuberías?
111
Intenté buscar en la red, pero apenas hay recursos. Bastaría un pequeño ejemplo.
EDITAR Quiero decir, dos programas C diferentes que se comunican entre sí. Un programa debería enviar "Hola" y el otro debería recibirlo. Algo como eso.
¿Presumiblemente no te refieres a algo como ls | grep ".o"? Quizás una explicación un poco más de lo que quiere decir ayudaría ...
Jerry Coffin
13
Vamos hombre ... un poco de esfuerzo. Google "código de ejemplo de tuberías c". El primer resultado es exacto: tldp.org/LDP/lpg/node11.html
Stephen
4
Quiero comunicación entre dos programas completamente diferentes. No pude encontrar un recurso para eso.
1
Si no está bifurcando un proceso, debe buscar en "tuberías con nombre".
Juez Maygarden
Respuestas:
156
Una tubería normal solo puede conectar dos procesos relacionados. Es creado por un proceso y desaparecerá cuando el último proceso lo cierre.
Una tubería con nombre , también llamada FIFO por su comportamiento, se puede utilizar para conectar dos procesos no relacionados y existe independientemente de los procesos; lo que significa que puede existir incluso si nadie lo está usando. Se crea un FIFO utilizando la mkfifo()función de biblioteca.
Ejemplo
escritor.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;}
reader.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;}
Nota: La comprobación de errores se omitió en el código anterior para simplificar.
Probablemente procesos que están relacionados a través de una o más relaciones padre / hijo (por ejemplo, incluye hermanos). El ancestro común habría creado los dos extremos de la tubería. Los procesos no relacionados carecen de ese ancestro común.
MSalters
4
Esto no funcionará si el lector comienza primero. Una solución rápida sería poner el open()del lector dentro de un bucle. Sin embargo +1 porque proporciona un ejemplo de dos programas.
gsamaras
Supongo que este ejemplo necesita algunos ajustes para funcionar en Windows. unistd.h siendo POSIX y todo ...
Además, puede obtener el efecto de prog1 | prog2enviar la salida de prog1a stdout y leer desde stdinin prog2. También puede leer stdin abriendo un archivo llamado /dev/stdin(pero no estoy seguro de la portabilidad de eso).
/*****************************************************************************
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);}
Hola Stephen, de todos modos, ¿puedo usar este código para dos funciones diferentes? lo que significa que la escritura en la tubería se realiza en una función y la lectura de la tubería en otra función. Se agradecería un código de trabajo como este.
Lo que un programa escribe en stdout puede ser leído por otro a través de stdin. Así que simplemente, usando c, escriba prog1para imprimir algo usando printf()y prog2para leer algo usando scanf(). Entonces solo corre
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;}
Los pasos importantes de este programa son:
La popen()llamada que establece la asociación entre un proceso hijo y una tubería en el padre.
los fprintf() llamada que usa la tubería como un archivo ordinario para escribir en el stdin del proceso hijo o leer desde su stdout.
La pclose()llamada que cierra la tubería y hace que termine el proceso hijo.
Creo que este ejemplo pierde el sentido de la pregunta, aunque reconozco que el programa "convertidor" es un programa diferente. El primer comentario aborda la comunicación entre programas completamente independientes que no tienen una relación de hermano / padre / primo segundo.
cmm
2
Primero, stdouthaga que el programa 1 escriba la cadena (como si quisiera que apareciera en la pantalla). Luego, el segundo programa debería leer una cadena de stdin, como si un usuario estuviera escribiendo desde un teclado. luego corres:
Esta respuesta podría ser útil para un futuro 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);}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;}
Puede encontrar un ejemplo avanzado de llamada de canalización bidireccional aquí .
ls | grep ".o"
? Quizás una explicación un poco más de lo que quiere decir ayudaría ...Respuestas:
Una tubería normal solo puede conectar dos procesos relacionados. Es creado por un proceso y desaparecerá cuando el último proceso lo cierre.
Una tubería con nombre , también llamada FIFO por su comportamiento, se puede utilizar para conectar dos procesos no relacionados y existe independientemente de los procesos; lo que significa que puede existir incluso si nadie lo está usando. Se crea un FIFO utilizando la
mkfifo()
función de biblioteca.Ejemplo
escritor.c
reader.c
Nota: La comprobación de errores se omitió en el código anterior para simplificar.
fuente
open()
del lector dentro de un bucle. Sin embargo +1 porque proporciona un ejemplo de dos programas.Desde Crear tuberías en C , esto le muestra cómo bifurcar un programa para usar una tubería. Si no quiere fork (), puede usar canalizaciones con nombre .
Además, puede obtener el efecto de
prog1 | prog2
enviar la salida deprog1
a stdout y leer desdestdin
inprog2
. También puede leer stdin abriendo un archivo llamado/dev/stdin
(pero no estoy seguro de la portabilidad de eso).fuente
Y leer:
Pero creo que
fcntl
puede ser una mejor soluciónfuente
Lo que un programa escribe en stdout puede ser leído por otro a través de stdin. Así que simplemente, usando c, escriba
prog1
para imprimir algo usandoprintf()
yprog2
para leer algo usandoscanf()
. Entonces solo correfuente
He aquí una muestra :
Los pasos importantes de este programa son:
popen()
llamada que establece la asociación entre un proceso hijo y una tubería en el padre.fprintf()
llamada que usa la tubería como un archivo ordinario para escribir en el stdin del proceso hijo o leer desde su stdout.pclose()
llamada que cierra la tubería y hace que termine el proceso hijo.fuente
Primero,
stdout
haga que el programa 1 escriba la cadena (como si quisiera que apareciera en la pantalla). Luego, el segundo programa debería leer una cadena destdin
, como si un usuario estuviera escribiendo desde un teclado. luego corres:fuente
Esta respuesta podría ser útil para un futuro Googler.
Puede encontrar un ejemplo avanzado de llamada de canalización bidireccional aquí .
fuente