簡體   English   中英

是否可以使用C ++流類來緩沖從管道讀取的內容?

[英]Is it possible to use a C++ stream class to buffer reads from a pipe?

簡而言之,可以按照此偽示例描述的內容從流類的管道中進行緩沖讀取。

請忽略您看到的所有問題(例如不檢查錯誤等); 我正在用我的真實代碼進行所有操作,這只是一個偽示例,可以解決我的問題。

#include <iostream> // or istream, ifstream, strstream, etc; whatever stream could pull this off
#include <unistd.h>
#include <stdlib.h>
#include <sstream>

void myFunc() {
  int pipefd[2][2] = {{0,0},{0,0}};

  pipe2( pipefd[0], O_NONBLOCK );
  pipe2( pipefd[1], O_NONBLOCK );

  if( 0 == fork() ) {
    close( pipefd[0][1] );
    close( pipefd[1][1] );
    dup2( pipefd[0][0], stdout );
    dup2( pipefd[1][0], stderr );
    execv( /* some arbitrary program */ );
  } else {
    close( pipefd[0][0] );
    close( pipefd[1][0] );

    /* cloudy bubble here for the 'right thing to do'.
     * Obviously this is faulty code; look at the intent,
     * not the implementation.
     */
#ifdef RIGHT_THING_TO_DO
    for( int ii = 0; ii < 2; ++ii ) {
      cin.tie( pipefd[ii][1] );
      do {
        cin.readline( /* ... */ );
      } while( /* ... */ );
    }
#else
    // This is what I'm doing now; it works, but I'm
    // curious whether it can be done more concisely
    do {
      do {
        select( /* ... */ );
        for( int ii = 0; ii < 2; ++ii ) {
          if( FD_SET( fd[ii][1], &rfds ) ) {
            read( fd[ii][1], buff, 4096 );
            if( /* read returned a value > 0 */ ) {
              myStringStream << buff;
            } else {
              FD_CLR( fd[ii][1], &rfds );
            }
          }
        }
      } while( /* select returned a value > 0 */ );
    } while( 0 == waitpid( -1, 0, WNOHANG ) );
#endif
  }
}

編輯

這是一個簡單的示例,說明如何使用boost::file_descriptor處理管道。 也應該與套接字一起使用,雖然沒有測試。

這是我的編譯方式:

g++ -m32 -DBOOST_IOSTREAMS_NO_LIB -isystem ${BOOST_PATH}/include \
  ${BOOST_SRC_PATH}/libs/iostreams/src/file_descriptor.cpp blah.cc -o blah

例子如下:

#include <fcntl.h>
#include <stdio.h>

#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>

int main( int argc, char* argv[] ) {
  // if you just do 'using namespace...', there's a
  // namespace collision with the global 'write'
  // function used in the child
  namespace io = boost::iostreams;

  int pipefd[] = {0,0};
  pipe( pipefd, 0 );  // If you use O_NONBLOCK, you'll have to
                      // add some extra checks to the loop so
                      // it will wait until the child is finished.

  if( 0 == fork() ) {
    // child
    close( pipefd[0] ); // read handle
    dup2( pipefd[1], FILENO_STDOUT );
    printf( "This\nis\na\ntest\nto\nmake sure that\nit\nis\working as expected.\n" );
    return 0; // ya ya, shoot me ;p
  }

  // parent

  close( pipefd[1] ); // write handle

  char *buff = new char[1024];
  memset( buff, 0, 1024 );

  io::stream<io::file_descriptor_source> fds(
    io::file_descriptor_source( pipefd[0], io::never_close_handle ) );

  // this should work with std::getline as well
  while(   fds.getline( buff, 1024 )
        && fds.gcount() > 0 // this condition is not enough if you use
                            // O_NONBLOCK; it should only bail if this
                            // is false AND the child has exited
       ) {
    printf( "%s,", buff );
  }

  printf( "\n" );
}

肯定有。 《 C ++標准庫:教程和參考》一書中有一個示例,說明如何制作包裝文件描述符(如從pipe()獲得的描述符)的std :: streambuf。 因此,在其之上創建流是微不足道的。

編輯:這是本書: http : //www.josuttis.com/libbook/

以下是使用文件描述符的示例輸出緩沖區: http : //www.josuttis.com/libbook/io/outbuf2.hpp.html

另外,這是一個示例輸入緩沖區: http : //www.josuttis.com/libbook/io/inbuf1.hpp.html

您想要一個可以使用現有文件描述符創建的流,或者想要一個本身創建管道的流。 不幸的是,沒有這樣的標准流類型。

您可以自己編寫或使用,例如boost :: iostreams :: file_descriptor

編寫自己的代碼需要先創建basic_streambuf的子類,然后再創建一個非常簡單的basic_i / ostream子類,該子類只不過保留了streambuf類並提供了方便的構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM