用C++创建rw管道的最佳方式是什么?

问题描述:

我有需要将命令发送到节目B的stdin和读回该程序B的输出的程序的(在C++编程,不仅LINUX)用C++创建rw管道的最佳方式是什么?

ProgramA - >发送字母A - >程序B 程序A < - B的输出< - 程序B

我实际上有第一部分,发送命令给B,使用popen()。我知道popen只是一种方式。

那么,使用C++进行双向的最佳方式是什么?

+0

您的标签提示了一个linux解决方案,但文本显示“不是只有unix”,所以只有一个* nix解决方案是否可行? – 2010-08-12 14:07:21

+0

我将文本更改为linux,因为我正在使用它,但是,* nix解决方案应该没问题。 – 2010-08-12 14:15:52

使用posix功能(所以,将在linux和任何符合posix标准的系统上工作),您可以使用pipe/execl/dup的组合。总之什么情况是:

  • 创建2个管道(一个读和一个写孩子)
  • 叉当前进程。这保持打开关闭当前stdin/stdout相同的fd
  • 。然后使用DUP(它使用的最低可用描述符重复你给它)
  • execl的子进程

讲究,需要一些刷新。 父的代码是:

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    pid_t pid; 
    int pipe_in[2]; /* This is the pipe with wich we write to the child process. */ 
    int pipe_out[2]; /* This is the pipe with wich we read from the child process. */ 

    if (pipe (pipe_in) || pipe (pipe_out)) { 
     fprintf (stderr, "Error in creating pipes!\n"); 
     exit (1); 
    } 

    /* Attempt to fork and check for errors */ 
    if ((pid = fork()) == -1) { 
     fprintf (stderr, "Error in fork!\n"); 
     exit (1); 
    } 

    if (pid) { 
     /* The parent has the non-zero PID. */ 
     char temp[100]; 
     int result; 
     FILE* child_in; 
     FILE* child_out; 

     child_in = fdopen(pipe_out[0],"r"); 
     child_out = fdopen(pipe_in[1],"w"); 
     close(pipe_out[1]); 
     close(pipe_in[0]); 

     fprintf(child_out, "something\n"); 

     fgets(temp,100,child_in); 
     printf(" Read from child %s \n", temp); 

     /* Send a command to the child. */ 
     fprintf(child_out, "quit\n"); 
     fflush(child_out); 

     fgets(temp,100,child_in); 
     printf(" Read from child %s \n", temp); 

     wait (&result);    /* Wait for child to finish */ 
    } 
    else { 
     /* The child has the zero pid returned by fork*/ 
     close (1); 
     dup (pipe_out[1]); /* dup uses the lowest numbered unused file descriptor as new descriptor. In our case this now is 1. */ 

     close (0);   /* dup uses the lowest numbered unused file descriptor as new descriptor. In our case this now is 0. */ 
     dup (pipe_in[0]); 

     close (pipe_out[0]); 
     close (pipe_out[1]); 
     close (pipe_in[0]); 
     close (pipe_in[1]); 
     execl ("child", "child", NULL); 
     exit(1); /* Only reached if execl() failed */ 
    } 
    return 0; 
} 

一个简单的孩子是:

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    char temp[100]; 

    do { 
     printf ("In child: \n"); 
     fflush (stdout); 
     fgets (temp, 100, stdin); 
     printf ("Child read %s\n", temp); 
     fflush (stdout); 
    } while (!strstr (temp, "quit")); 

    return 0; 
} 

您可以编译他们:

gcc -o parent parent.c 
gcc -o child child.c 
./parent 

你会看到从阅读

小孩在小孩: 从小孩读取小孩阅读退出

+0

最好使用'dup2',它允许您指定要使用的新文件描述符。 – dreamlax 2010-08-13 01:11:36

+0

谢谢,我可以做这个工作。 – 2010-08-13 16:04:31

查看here来自Jeremy Siek(谁在许多助推库上工作)的一个非常密切相关的问题。当时(2002年),它似乎是唯一可以回答你的问题的答案,可以在ACE库中找到。有关更多信息,请参见here

不确定这是对您问题的正确答案,但可能有所帮助。

您可以尝试从Glib的g_spawn_async_with_pipes

该函数运行一个进程并返回其输入/输出文件描述符。

我用它在我的C++程序:

gchar** cmd_argv; 
g_shell_parse_argv("your command", &cmd_argc, &cmd_argv, NULL); 
g_spawn_async_with_pipes 
(NULL, //Working directory, Inherited from parent (our program) 
    cmd_argv, 
    NULL, //Null to inherit environment variables from parent 
    G_SPAWN_SEARCH_PATH, //Flags 
    NULL, 
    NULL, 
    NULL, //Returns the process ID of child (which runs from our program) 
    &stdin_fd, //Standard input (file descriptor) 
    &stdout_fd, //Standard output (file descriptor) 
    &stderr_fd, //Standard error (file descriptor) 
    NULL); //GError* 

... 

//we have to free cmd_argv 
for (int i = 0; i < cmd_argc; ++i) g_free (cmd_argv [i]); 

stdin_fdstdout_fdstderr_fd是整数(文件描述符):

gchar* out; 
GIOChannel* io = g_io_channel_unix_new(stdout_fd); //g_io_channel_win32_new_fd 
while(g_io_channel_read_line(io, &out, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) 
{ 
    //... 
    g_free(out); 
} 

但是它不是一个C++库,但可能是有用的(当你想用C++编写GTK应用程序时)。