Как отправить простую строку между двумя программами с помощью каналов?
111
Пытался поискать в сети, но ресурсов почти нет. Достаточно небольшого примера.
ИЗМЕНИТЬ Я имею в виду, две разные программы на C, взаимодействующие друг с другом. Одна программа должна послать «Привет», а другая - получить его. Что-то такое.
По-видимому, вы не имеете в виду что-то вроде ls | grep ".o"? Возможно, поможет более подробное объяснение того, что вы имеете в виду ...
Джерри Коффин,
13
Давай, чувак ... немного усилий. Google "пример кода c pipe". Первый результат точен: tldp.org/LDP/lpg/node11.html
Стивен
4
Я хочу общения между двумя совершенно разными программами. Мне не удалось найти для этого ресурс.
1
Если вы не разветвляете процесс, вам нужно посмотреть на «именованные каналы».
Судья Мэйгарден,
Ответы:
156
Обычный канал может соединять только два связанных процесса. Он создается процессом и исчезнет, когда его закроет последний процесс.
Именованный канал , называемый также буфер FIFO для его поведения, может быть использован для соединения двух несвязанных процессов и существует независимо от процессов; это означает, что он может существовать, даже если его никто не использует. FIFO создается с помощью mkfifo()библиотечной функции.
пример
писатель.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;}
Примечание. Для простоты в приведенном выше коде опущена проверка ошибок.
Вероятно, процессы, которые связаны через одно или несколько родительских / дочерних отношений (например, включают братьев и сестер). Общий предок создал бы два конца трубы. У несвязанных процессов нет общего предка.
MSalters 05
4
Это не сработает, если читатель начнет первым. Быстрое исправление - поместить open()читателя в цикл. Однако +1, потому что вы предоставляете пример двух программ.
gsamaras
Я так понимаю, что этот пример требует некоторой настройки для работы с Windows? unistd.h - это POSIX и все такое ...
Кроме того, вы можете получить эффект prog1 | prog2, посылая вывод prog1на стандартный вывод и чтение из stdinв prog2. Вы также можете прочитать stdin, открыв файл с именем /dev/stdin(но не уверены в его переносимости).
/*****************************************************************************
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);}
Привет, Стивен, в любом случае я могу использовать этот код для двух разных функций? это означает, что запись в канал выполняется одной функцией, а чтение канала - в другой функции ?? был бы признателен за такой рабочий код.
То, что одна программа записывает в стандартный вывод, может быть прочитано другой через стандартный ввод. Итак, просто, используя c, напишите, prog1чтобы что-то напечатать, используя, printf()а prog2чтобы прочитать, используя scanf(). Тогда просто беги
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;}
Важные шаги в этой программе:
popen()Вызов , который устанавливает связь между дочерним процессом и трубами в родителю.
fprintf()Вызов , который использует канал как обычный файл для записи на стандартный ввод дочернего процесса или читать его на стандартный вывод.
pclose()Вызов , который закрывает трубу и вызывает дочерний процесс завершается.
Я думаю, что этот пример упускает суть вопроса, хотя я допускаю, что программа-преобразователь - это другая программа. Первый комментарий касается взаимодействия между полностью независимыми программами, у которых нет родственных отношений между братьями и сестрами / родителями / троюродными братьями.
cmm
2
Сначала попросите программу 1 записать строку в stdout(как если бы вы хотели, чтобы она отображалась на экране). Затем вторая программа должна прочитать строку stdin, как если бы пользователь печатал с клавиатуры. затем вы запускаете:
#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;}
Вы можете найти продвинутый двухсторонний пример вызова трубы здесь .
ls | grep ".o"
? Возможно, поможет более подробное объяснение того, что вы имеете в виду ...Ответы:
Обычный канал может соединять только два связанных процесса. Он создается процессом и исчезнет, когда его закроет последний процесс.
Именованный канал , называемый также буфер FIFO для его поведения, может быть использован для соединения двух несвязанных процессов и существует независимо от процессов; это означает, что он может существовать, даже если его никто не использует. FIFO создается с помощью
mkfifo()
библиотечной функции.пример
писатель.c
reader.c
Примечание. Для простоты в приведенном выше коде опущена проверка ошибок.
источник
open()
читателя в цикл. Однако +1, потому что вы предоставляете пример двух программ.В разделе «Создание каналов на языке C» показано, как создать вилку программы для использования канала. Если вы не хотите использовать fork (), вы можете использовать именованные каналы .
Кроме того, вы можете получить эффект
prog1 | prog2
, посылая выводprog1
на стандартный вывод и чтение изstdin
вprog2
. Вы также можете прочитать stdin, открыв файл с именем/dev/stdin
(но не уверены в его переносимости).источник
И читать:
Но я думаю, что это
fcntl
может быть лучшим решениемисточник
То, что одна программа записывает в стандартный вывод, может быть прочитано другой через стандартный ввод. Итак, просто, используя c, напишите,
prog1
чтобы что-то напечатать, используя,printf()
аprog2
чтобы прочитать, используяscanf()
. Тогда просто бегиисточник
Вот образец :
Важные шаги в этой программе:
popen()
Вызов , который устанавливает связь между дочерним процессом и трубами в родителю.fprintf()
Вызов , который использует канал как обычный файл для записи на стандартный ввод дочернего процесса или читать его на стандартный вывод.pclose()
Вызов , который закрывает трубу и вызывает дочерний процесс завершается.источник
Сначала попросите программу 1 записать строку в
stdout
(как если бы вы хотели, чтобы она отображалась на экране). Затем вторая программа должна прочитать строкуstdin
, как если бы пользователь печатал с клавиатуры. затем вы запускаете:источник
Этот ответ может быть полезен будущему гуглеру.
Вы можете найти продвинутый двухсторонний пример вызова трубы здесь .
источник