定期读取使用dup2重定向到管道的stdout内容的问题

时间:2010-08-09 06:29:30

标签: c unix

我必须定期读取重定向到文件的stdout的内容。请帮我解决问题。

我的问题是我在第一个线程中有两个线程,我必须执行一个c文件  它不断地将输出写入stdout(即在无限循环中编写hello world)和  在第二个线程中,我必须从stdout定期检索逐行输出并存储在缓冲区中。

以下是上述要求的代码:请建议我是我的做法对吗?  以及如何实现entryOpThread()方法,以便它定期读取stdout的内容  是否应该使用read()系统调用或getLine()或任何其他方法逐行读取  管道(stdout被重定向到此管道)。  在这个例子中,exec线程正在执行test.c,它在stdout上连续打印hello world,  所以根据我的要求,我必须在管道的Outputthread中连续读取此输出(“Hello world”)并将其存储在缓冲区中 //

#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 :(得分:0)

发送到管道的数据是缓冲的,因此您不需要其他缓冲区。只要有需要,只需从管道中读取数据即可。您可以使用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);
    }
}

如果此解决方案不符合您的需求,请写出问题所在。