Подскажите пожалуйста, как заставить дочерний, exec()-нутый процесс
общаться с родителем через pipe. Совсем запутался в изобилии
документации :(
Вроде бы надо передать дочернему значения файловых дескрипторов,
которые pipe() инициализирует, а как - не могу додуматься.
Или может, есть другой способ заставить дочерний процесс
писать в pipe, созданный родителем?PS
Извините, если неправильно задал вопрос - первый раз тут пишу :)
>Подскажите пожалуйста, как заставить дочерний, exec()-нутый процесс
>общаться с родителем через pipe. Совсем запутался в изобилии
>документации :(
>Вроде бы надо передать дочернему значения файловых дескрипторов,
>которые pipe() инициализирует, а как - не могу додуматься.
>Или может, есть другой способ заставить дочерний процесс
>писать в pipe, созданный родителем?
>
>PS
>Извините, если неправильно задал вопрос - первый раз тут пишу :)На самом деле все довольно просто. Самый простой способ - использовать команду popen для открытия пипы к команде и pclose для закрытия.
Example:#include <stdio.h>
int main( int argc, char* argv[] )
{
FILE* fp;
// Откроем пипу к команде wc на запись
fp = popen("wc", "w" );
if( fp )
{
fprintf( fp, "My string\n" );
pclose( fp );
}
else
{
perror("popen");
return 1;
}
return 0;
}Недостатки этого метода - для выполнения команды запускается шелл, что нужно далеко не всегда.
pipe Parent to child
//------------------------------------------------------------
#include <stdio.h> // printf
#include <string.h> // memset
#include <sys/types.h> // for pid_t
#include <unistd.h> // fork, read, writechar msg[] = "hello from parent process";
char buf[100];int main( int argc, char* argv[] )
{
int filedes[2];
pid_t pid;// Создадим пару файловых дескрипторов для пипы
if( pipe( filedes ) == -1 )
{
perror("pipe");
return 1;
}// Создадим процесс-потомок
pid = fork();// Оценим стуацию
if( pid == -1 )
{
perror( "fork" );
return 1;
}
// Родитель
if( pid )
{
// filedes[0] используется для чтения
close( filedes[0] );
printf( "Parent: sending message to child [ %d ]\n", pid );
write( filedes[1], msg, sizeof(msg) );
close( filedes[1] );
}
// Потомок
else
{
// filedes[1] используется для записи
close( filedes[1] );
memset( buf, 0, sizeof(buf) );
read( filedes[0], buf, sizeof(msg) );
close( filedes[0] );
printf( "Child: parent say: %s\n", buf );
}return 0;
}В этой проге есть недоработки, но общий принцип примерно такой.
dimus, прошу прощения, наверное я должен был акцентировать то, что
дочерний процесс именно exec-нутый, то есть это вторая программа-клиент,
которая должна будет посылать первой программе-серверу весточку через
pipe.Так что приведенные Вами коды, к сожалению, не решат проблему (в первом
можно только команды shell, во втором использован fork() )
>можно только команды shell, во втором использован fork() )
В этом случае можно открывать pipe, по затем закрыть например stdin, продублировать дескриптор, закрыть ненужный старый, а новый дубль будет открыт заместо stdin, тогда после exec программа будет знать, через что ей общаться с родителем.
>dimus, прошу прощения, наверное я должен был акцентировать то, что
>дочерний процесс именно exec-нутый, то есть это вторая программа-клиент,
>которая должна будет посылать первой программе-серверу весточку через
>pipe.
>
>Так что приведенные Вами коды, к сожалению, не решат проблему (в первом
>
>можно только команды shell, во втором использован fork() )Почему только шелл? Любые команды. Просто при их запуске вызывается шелл, если конечно man popen не врет.
Во втором случае использован форк, но если мы запустим потом exec, то процесс унаследует дескриптор стандартного ввода от своего предка. Т.е. после форка, но перед exec нам надо продублировать выходной конец пипы на стандартный ввод дочернего процесса. См. ман по функции dup2.
Переназначение стандартных потоков сработало с первого раза! :)Правда, понял я это намного позже, переписав двадцать раз клиентскую часть - только тогда я вспомнил, что у меня везде для контроля понапихано команд ps, и они мне вместо экрана как раз в pipe и отчитывались :)
Спасибо вам, dimus и Forth, за объяснения. Я уже натыкался на http://www.opennet.me/base/patch/dup2.txt.html , но не понял тогда, что там как раз моя проблема описана. Цитаты там порезаны максимально - борьба с оверквотингом, это хорошо, конечно, но в меру :)