Python 使用stdout/stderr以外的管道与子流程通信

Python 使用stdout/stderr以外的管道与子流程通信,python,c++,linux,Python,C++,Linux,这是我分叉/执行子流程并与其通信的方式(伪代码): 我的问题是: 我真的不想读取子进程的标准输出,我希望子进程在标准输出以外的文件描述符上写入。我希望上面的代码能够从文件描述符中读取 子进程用Python编写,C++中的主要过程。 我想我可以改变这一行,从: dup2(cout_pipe[1],STDOUT_FILENO); 到 并以我自己的随机FD编号而不是标准输出的方式对子流程进行编码 这是一个好的解决方案吗?可行吗?我怎样才能算出一个好的我自己的随机数?有更好的替代方案吗?在您描述的情况

这是我分叉/执行子流程并与其通信的方式(伪代码):

我的问题是:

我真的不想读取子进程的标准输出,我希望子进程在标准输出以外的文件描述符上写入。我希望上面的代码能够从文件描述符中读取

子进程用Python编写,C++中的主要过程。 我想我可以改变这一行,从:

dup2(cout_pipe[1],STDOUT_FILENO);

并以我自己的随机FD编号而不是标准输出的方式对子流程进行编码


这是一个好的解决方案吗?可行吗?我怎样才能算出一个好的我自己的随机数?有更好的替代方案吗?

在您描述的情况下,不需要复制文件描述符。对pipe()的调用已经在cout_pipe数组中创建了所需的文件描述符

通常,子进程只是在执行之前关闭管道的读取端,而父进程关闭管道的写入端。子级将它想要的任何内容写入写入端,父级读取或以其他方式监视管道的读取端

如果您的问题是“在子进程调用execv()时,子进程如何知道其exec之后的fd号,那么我会说将其作为执行参数传递。”

比如:

int   child_pipe[2];
FILE *child_file;

void forkchild(void)
{
    int  ret;
    char child_pipe_fd_str[16];

    pipe(child_pipe);  /* TODO: check return value! */

    if (0 == (ret = fork())) /* child */
    {
        close(child_pipe[0]);
        sprintf(child_pipe_fd_str, "%d", child_pipe[1]);
        execv(my_python_script, child_pipe_fd_str, NULL);
    }
    else if (-1 != ret)  /* parent */
    {
        close(cout_pipe[1]);
        child_file = fdopen(cout_pipe[0], "r");
    }
    else
    {
        perror("Fork failed!");
        abort();
    }
}

除非您想要一个特定的fd,比如标准输出,否则在
dup2
中没有任何意义。只需将
cout\u pipe[1]
转换为字符串,并将其作为命令行参数传递给子级(在
exec
中)。在Python端,从
sys.argv
中提取参数,将其转换回
int
,并使用
os.fdopen
为其获取
文件。

在上述情况下,当child写入stdout时,stdout先前被重定向到管道,因此,父进程只需从管道中读取,就可以读取子进程的标准输出。我希望子进程不写入标准输出,而是写入另一个文件,并且父进程可以读取它。如果要将管道的写入端包装到文件中,请在执行后在子进程中调用fdopen(write_-side,“w”)。诀窍是在执行exec之后,了解子级中管道写入端的文件描述符。一种方法是在调用execv()时显式地将其作为执行参数传递。明白了吗?好的,我应该在fork之后,exec之前创建一个文件,然后是dup2(cout_pipe[1],this_files_fd),然后将文件的fd作为exec的参数传递给subprocess,然后用python写入这个fd?不,应该在exec之后,在新的python进程内使用os.fdopen创建文件结构。诀窍是知道你需要打开什么fd。您应该将其作为执行参数传递给子C进程中的execv()。我将在我的答案中发布一些代码。是否将cout_pipe[1]转换为字符串?这意味着管道(cout_-pipe)使cout_-pipe[1]成为有效的fd?。另外,转换itoa(cout_pipe[1])的最佳方式是什么?@Kam
pipe(cout_pipe)
将管道的两个fd放入
cout_pipe
。您可能希望使用
dup2
的唯一原因是您对fd的数值不满意。至于转换,任何标准溶液都可以;如果您在子端执行此操作,紧接着执行
exec
,并且您的系统具有
itoa
(这不是标准),那么即使这样也可以接受;如果您使用的是C++11,那么可以使用
std::to_string
——在调用
.C_str()
之前,请确保将结果保存到一个具有足够生存期的变量中。
dup2(cout_pipe[1],MY_OWN_RANDOM_FD_NUMBER);
int   child_pipe[2];
FILE *child_file;

void forkchild(void)
{
    int  ret;
    char child_pipe_fd_str[16];

    pipe(child_pipe);  /* TODO: check return value! */

    if (0 == (ret = fork())) /* child */
    {
        close(child_pipe[0]);
        sprintf(child_pipe_fd_str, "%d", child_pipe[1]);
        execv(my_python_script, child_pipe_fd_str, NULL);
    }
    else if (-1 != ret)  /* parent */
    {
        close(cout_pipe[1]);
        child_file = fdopen(cout_pipe[0], "r");
    }
    else
    {
        perror("Fork failed!");
        abort();
    }
}