dup2 () и exec () - PullRequest
       37

dup2 () и exec ()

5 голосов
/ 13 февраля 2011
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int
main( int argc, char **argv)
{
    int pfds[ 2], i;
    size_t pbytrd;
    pid_t childpid;
    char buffer[ 200];

    pipe( pfds);
    if( ( childpid = fork() ) == -1)
    {
            perror( "fork error: ");
            exit( 1);
    }
    else if( childpid == 0)
    {
            close( pfds[ 0]);
            dup2( pfds[1], 1);
            close( pfds[ 1]);
            for( i = 0; i < 10; i++)
               printf("Hello...");
            execlp( "xterm","xterm","-e","./sample_a", (char *) 0);
            exit( 0);
}
else
{

        close( pfds[ 1]);
        for( ; ; )
        {
            if( ( pbytrd = read( pfds[ 0], buffer, sizeof( buffer) ) ) == -1)
            {
                perror(" read error: ");
                exit( 1);
            }
            else if( pbytrd == 0)
            {

                write( fileno( stdout), "Cannot read from pipe...\n", strlen( "Cannot read from pipe...\n") );
                exit( 0);
            }
            else
            {
                write( fileno( stdout), "MESSAGE: ", strlen( "MESSAGE: ") );
                write( fileno( stdout), buffer, pbytrd);
            }
        }       
}   
return( 0);

}

Мой код sample_a.c ниже:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int
main( int argc, char **argv)
{
        int i;
        for( i= 0; i< 10; i++)
        write( fileno( stdout), "Hello...", strlen( "Hello...") );
    return( 0);
 }

В приведенном выше коде я действительно хочу сделать следующее: 1) Перенаправить вывод из дочернего процесса в канал и получить родительское чтение из канала и распечатать его на стандартный вывод.

Я могу перенаправить вывод дочернего процесса ("printf") из stdout в канал, но не могу перенаправить вывод дочернего процесса execlp, xterm, в канал.

Кто-нибудь может мне в этом помочь?

Ответы [ 4 ]

4 голосов
/ 13 февраля 2011

xterm - эмулятор терминала.Он выполняет предоставленную вами программу (sample_a), соединяя свои входы и выходы с самим собой, так что программа получает пользовательские входные данные на своем стандартном входном сигнале и печатает для пользователя все, что отправляет на свои стандартные и выходные сообщения об ошибках.

Что ваша программа делает, чтобы подключить выход xterm к каналу и пытается прочитать это.Но xterm - это программа с графическим интерфейсом, обычно она не записывает данные на свои выходы.Возможно, не совсем понятно, чего именно вы пытаетесь достичь.

Если вы удалите часть xterm, она должна работать так, как вы ожидаете, то есть родительский процесс увидит, что sample_a пишет ввыход.

        execlp("./sample_a", "./sample_a", (char *) 0);
1 голос
/ 02 октября 2014

Массив pipeFD хранит два описания файлов входа и выхода после того, как вы создали окно xterm. Дочерний процесс не знает, куда писать. Таким образом, вы можете использовать dup2:

dup2(pipeFD[1],100);
close(pipeFD[1]);

Отображает старый порт записи на новый порт (другие номера также работают). А в xterm вы можете написать в трубу по

write(100,"something you wanna to write").
1 голос
/ 20 сентября 2011

Я столкнулся с подобной ситуацией. Моей целью было отправить некоторую информацию из дочернего процесса, который выполняется в xterm. Как также сообщалось ранее, я не смог использовать dup2. Обходной путь для этого состоит в том, чтобы передать fd в новый двоичный файл как аргументы xterm.

Предлагаемый подход (без проверки ошибок на краткость):

if (childpid  == 0)
{
    /* child closes read*/
    close(pipeFD[0]);
    char writeFD[10]; // do consider space for '\0'
    /* Extract the write fd and put it in a char buffer 
       make compatible as per execlp args */
    sprintf(writeFD, "%d", pipeFD[1]); 
    /* just pass the writeFD as an arg */
    execlp("xterm", "xterm", "-e", "./binary", writeFD, (char *) 0))

}
else
{
    /* parent closes write */
    close(pipeFD[1]);
    if((bytesRead = read(pipeFD[0], buf, SIZE)) != -1)
    {
        printf("Recieved %s\n", buf);
        close(pipeFD[0]);
    }
 }

В дочернем процессе, который выполняется в xterm, извлеките fd

main(int argc, char** argv) {
   int fd = atoi(argv[1]);
   write(fd, buf,sizeof(buf));
}     

Я не знаю, почему dup2 не работает с xterm, но этот обходной путь отвечает требованию.

1 голос
/ 13 февраля 2011

xterm не имеет выходных данных, поэтому нет способа перенаправить его куда-либо. xterm запускает дочерний процесс и перенаправляет выходные данные дочернего элемента на себя, поэтому, если вы хотите перенаправить выходные данные дочернего элемента куда-либо, кроме xterm, вам нужно будет сделать это самостоятельно в дочернем элементе, ПОСЛЕ xterm, запускает его. Самый простой способ сделать это, вероятно, заставить xterm запустить оболочку и использовать перенаправление оболочки. Чтобы перенаправить только stderr для ребенка, вы должны использовать что-то вроде:

execlp("xterm", "xterm", "-e", "/bin/sh", "-c", "./sample_a 2>somewhere", 0);

замена somewhere на что-то подходящее. Предполагая, что вы хотите записать это в своей исходной программе, вы, вероятно, захотите создать временный fifo с помощью tempnam (3) и mkfifo (3) и открыть его для чтения в родительской программе. Вам нужно создать его перед разветвлением и открыть его после разветвления, поскольку open будет блокироваться, пока оболочка не запустится, и не откроет конец записи. После того, как открытие завершено, вы можете удалить fifo и прочитать из теперь безымянного fifo.

...