Проблема с периодическим чтением содержимого стандартного вывода, перенаправленного на канал с использованием dup2 - PullRequest
1 голос
/ 09 августа 2010

Я должен периодически читать содержимое стандартного вывода, которое перенаправляется в файл. Пожалуйста, помогите мне решить проблему.

Моя проблема в том, что у меня есть два потока в первом потоке, я должен выполнить файл c который непрерывно записывает вывод в stdout (т.е. пишет привет мир в бесконечном цикле) и во втором потоке я должен периодически извлекать построчную выдачу из stdout и сохранять в буфере.

Ниже приведен код для вышеуказанного требования: пожалуйста, предложите мне мой подход правильно? и как реализовать метод entryOpThread (), чтобы он периодически читал содержимое stdout должен ли я использовать read () системный вызов или getLine () или любой другой метод для чтения построчно из труба (стандартный поток перенаправлен на эту трубу). В этом примере поток exec выполняет test.c, который непрерывно печатает hello world на stdout, поэтому в соответствии с моим требованием я должен читать эту выходную строку построчно («Hello world») непрерывно в Outputthread из канала и сохранять его в буфере //

#include<iostream>
#include<pthread>
#include<unistd.h>
#include<sys/wait.h>
const int MAX_LENGTH=100;
using namespace std;

//! file descriptor to duplicate the system standard input 
int inputPIPE[2];



//! file descriptor to duplicate the system standard output
int OutputPipe[2];

//!Thread to retrieve output
//!
pthread_t OpThread;

//!Thread to execute script
//!
pthread_t ExecThread;


//! entry point of the exec thread
void *entryExecThread(void * obj)
{
    //create a child process to launch the script
    int lPid;
    lPid=fork();
    //connect read end of the pipe to the standard input
    if(dup2(inputPIPE[0],STDIN_FILENO)==-1)
    {
        //throw exception
    }

    //connect write end of the pipe to the standard output
    if(dup2(OutputPipe[1],STDOUT_FILENO)==-1)
    {
        //throw exception
    }
    if(lPid==0)
    {



        execvp("./test",NULL);
    }

    else
    {
        int mProcessId=lPid;
        waitpid(mProcessId,NULL,0);
    }
    return NULL;

}

//! entry point of the output thread
void *entryOpThread(void * obj)
{
    //read contents of stdout periodically
    char *lMssg=new char[MAX_LENGTH];
    read(OutputPipe[0],lMssg,MAX_LENGTH);

    FILE *fd=fdopen(OutputPipe[0],"r");
    int lBufferLength=MAX_LENGTH;
    /* while(true)
        {
            getline(&lMssg,(size_t * )&lBufferLength,fd);
            // push message to the output buffer
            if (lMssg !=NULL)
            {
                pthread_mutex_lock( &mOutputBufferMutex);
                mOutputBuffer.push(lMssg);
                pthread_mutex_unlock( &mOutputBufferMutex);
            }
        }
     */

}
int main() {

    //call to pipe system call
    if(pipe(inputPIPE)==-1)
    {
        printf("ERROR IN OPENING FILE \n");
    }
    if(pipe(OutputPipe)==-1)
    {
        printf("ERROR IN OPENING FILE\n ");
    }

    //CREATE OUTPUT THREAD TO RETRIEVE OUTPUT

    if (pthread_create(&OpThread,0,entryOpThread,NULL)!=0)
    {

        //throw exception
        printf("Creation of Output thread  failed for Script with ID\n");
    }

    //Create execution thread to launch script
    pthread_t execThread;
    if (pthread_create(&ExecThread,0,entryExecThread,NULL)!=0)
    {

        //Stop output thread
        pthread_cancel(OpThread);
        //throw exception
        printf("Creation of Execution thread  failed for Script with ID\n");
    }
}

test.c

#include <stdio.h>
#include "string.h"
//using namespace std;

int main() {
     int i=0;
     while(i<500)
    {
    printf("!!!Hello World!!! \n" ); // prints !!!Hello World!!!
    //extracting header and data from message
        sleep(5);
      i++;
    }   
    return 0;
}

1 Ответ

0 голосов
/ 09 августа 2010

Данные, отправляемые в канал, буферизуются, поэтому вам не нужен другой буфер.Просто читайте данные из канала всякий раз, когда это необходимо.Вы можете проверить, есть ли данные для чтения, используя функцию poll.Вам не нужен поток для чтения.

Также вам не нужен поток exec, потому что вы все равно fork.

Кроме того, ваше приложение будет прервано почти сразу, потому что основной потокможет закончиться после запуска вторичных потоков.

Другая вещь, на которую следует обратить внимание, это то, что вы должны закрыть ненужные дескрипторы.pipe открывает 2 дескриптора, fork дублирует все открытые дескрипторы, dup2 дублирует дескриптор.Вы не закрыли ничего.

Если вы просто хотите прочитать вывод какого-либо процесса, запустите его, используя popen.Ниже приведен короткий пример.

основное приложение:

int main()
{
    FILE *f = popen("./test", "r"); // open the process

    /* Your application is busy now, but the process runs and outputs */
    sleep(5);

    /* Now assume you need some data - just read it */
    int c;
    while (0 <= (c = fgetc(f))) putchar(c);
}

тестовое приложение:

int main()
{
    int i;
    for (i = 0; i < 10; i++) {
        puts("Hello world!");
        fflush(stdout);
        sleep(1);
    }
}

Если это решение не соответствует вашим потребностям, напишите, в чем проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...