URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 4846
[ Назад ]

Исходное сообщение
"Обмен по pipe между процессами"

Отправлено Shourikun , 16-Ноя-05 01:05 
Подскажите пожалуйста, как заставить дочерний, exec()-нутый процесс
общаться с родителем через pipe. Совсем запутался в изобилии
документации :(
Вроде бы надо передать дочернему значения файловых дескрипторов,
которые pipe() инициализирует, а как - не могу додуматься.
Или может, есть другой способ заставить дочерний процесс
писать в pipe, созданный родителем?

PS
Извините, если неправильно задал вопрос - первый раз тут пишу :)


Содержание

Сообщения в этом обсуждении
"Обмен по pipe между процессами"
Отправлено dimus , 16-Ноя-05 09:19 
>Подскажите пожалуйста, как заставить дочерний, 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 между процессами"
Отправлено dimus , 16-Ноя-05 09:47 
pipe Parent to child
//------------------------------------------------------------
#include <stdio.h>      // printf
#include <string.h>     // memset
#include <sys/types.h>  // for pid_t
#include <unistd.h>     // fork, read, write

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

В этой проге есть недоработки, но общий принцип примерно такой.


"Обмен по pipe между процессами"
Отправлено Shourikun , 16-Ноя-05 10:44 
dimus, прошу прощения, наверное я должен был акцентировать то, что
дочерний процесс именно exec-нутый, то есть это вторая программа-клиент,
которая должна будет посылать первой программе-серверу весточку через
pipe.

Так что приведенные Вами коды, к сожалению, не решат проблему (в первом
можно только команды shell, во втором использован fork() )



"Обмен по pipe между процессами"
Отправлено Forth , 16-Ноя-05 12:31 
>можно только команды shell, во втором использован fork() )
В этом случае можно открывать pipe, по затем закрыть например stdin, продублировать дескриптор, закрыть ненужный старый, а новый дубль будет открыт заместо stdin, тогда после exec программа будет знать, через что ей общаться с родителем.



"Обмен по pipe между процессами"
Отправлено dimus , 17-Ноя-05 09:33 
>dimus, прошу прощения, наверное я должен был акцентировать то, что
>дочерний процесс именно exec-нутый, то есть это вторая программа-клиент,
>которая должна будет посылать первой программе-серверу весточку через
>pipe.
>
>Так что приведенные Вами коды, к сожалению, не решат проблему (в первом
>
>можно только команды shell, во втором использован fork() )

Почему только шелл? Любые команды. Просто при их запуске вызывается шелл, если конечно man popen не врет.

Во втором случае использован форк, но если мы запустим потом exec, то процесс унаследует дескриптор стандартного ввода от своего предка. Т.е. после форка, но перед exec нам надо продублировать выходной конец пипы на стандартный ввод дочернего процесса. См. ман по функции dup2.


"Forth и dimus, спасибо большое!"
Отправлено Shourikun , 19-Ноя-05 03:35 
Переназначение стандартных потоков сработало с первого раза! :)

Правда, понял я это намного позже, переписав двадцать раз клиентскую часть - только тогда я вспомнил, что у меня везде для контроля понапихано команд ps, и они мне вместо экрана как раз в pipe и отчитывались :)

Спасибо вам, dimus и Forth, за объяснения. Я уже натыкался на http://www.opennet.me/base/patch/dup2.txt.html , но не понял тогда, что там как раз моя проблема описана. Цитаты там порезаны максимально - борьба с оверквотингом, это хорошо, конечно, но в меру :)