简体   繁体   English

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

[英]Issue in periodically reading contents of stdout redirected to pipe using dup2

I have to periodically read contents of stdout which is redirected to file. 我必须定期读取重定向到文件的stdout的内容。 please help me to resolve issue. 请帮助我解决问题。

My problem in detail is that i have two thread in first thread , i have to execute ac file which is continously writing output to stdout(ie writing hello world in infinite loop) and in second thread i have to retrieve line by line output periodically from stdout and store in buffer. 我的详细问题是我在第一个线程中有两个线程,我必须执行一个ac文件,该文件不断将输出写入stdout(即在无限循环中写入hello世界),而在第二个线程中,我必须定期从行中逐行检索输出标准输出并存储在缓冲区中。

Below is the code for above requirement: please suggest me is my approach right? 以下是上述要求的代码:请建议我我的方法正确吗? and how to implement entryOpThread() method so that it will read contents of stdout periodically whether should i use read() system call or getLine()or any other method to read line by line from pipe(stdout is redirected to this pipe). 以及如何实现entryOpThread()方法,以便它将定期读取stdout的内容,无论我应该使用read()系统调用还是getLine()或任何其他方法从管道逐行读取(stdout都重定向到此管道)。 In this example exec thread is executing test.c which is continuouslly printing hello world on stdout, so according to my requirement i have to read this output line by line("Hello world") continuouslly in Outputthread from pipe and store it in buffer // 在此示例中,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;
}

Data sent to a pipe is buffered so you don't need another buffer. 发送到管道的数据已缓冲,因此您不需要其他缓冲区。 Just read the data from a pipe whenever there is a need to. 只需在需要时从管道读取数据。 You can test whether there is a data to read using poll function. 您可以使用poll功能测试是否有要读取的数据。 You don't need the reader thread. 您不需要阅读器线程。

Also you don't need exec thread because you are fork 'ing anyway. 另外,您也不需要exec线程,因为无论如何您都fork

Besides your application would terminate almost immediately because the main thread would end up after firing secondary threads. 此外,您的应用程序几乎会立即终止,因为主线程将在触发辅助线程后终止。

Other thing to point out is that you should close unneeded handles. 要指出的另一件事是,您应该关闭不需要的句柄。 pipe opens 2 handles, fork duplicates all opened handles, dup2 duplicate a handle. pipe打开2个控柄, fork复制所有打开的控柄, dup2复制一个控柄。 You didn't close any. 您没有关门。

If you just want to read output of some process, run it using popen . 如果只想读取某个进程的输出,请使用popen运行它。 Below short example. 下面是简短的示例。

main app: 主要应用程式:

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

test app: 测试应用程序:

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

If this solution doesn't fit your needs then write what's the problem. 如果此解决方案无法满足您的需求,请写下问题所在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM