我们在 C 或 C++ 中是不是有类似于 IPC::Open3 的 perl

Posted

技术标签:

【中文标题】我们在 C 或 C++ 中是不是有类似于 IPC::Open3 的 perl【英文标题】:Do we have a anything similar to IPC::Open3 of perl in C or C++我们在 C 或 C++ 中是否有类似于 IPC::Open3 的 perl 【发布时间】:2018-01-18 08:29:09 【问题描述】:

我使用 perl 的 open3 来运行命令,自定义命令的行为就像一个 shell,它接受输入并显示输出并等待另一个输入直到给出退出

现在我要使用相同的命令并用 C 语言编写它,我们是否有类似于 C 或 C++ 中的 IPC::Open3 的东西?

【问题讨论】:

pipe() 和 fork() 可以做同样的事情,但当然要麻烦得多。首先阅读Safe Pipe Opens in perldoc perlipc,这是对这些概念的比较高级的讨论。然后,您可以将相同的概念转移到 Posix/C。 是的,我在看管道和叉子,但我无法让它工作,而且它超出了我的理解范围,我想这需要一些时间来克服它 在 C 中还是在 C++ 中?这是不一样的。 Windows 还是 Linux? 简而言之:system 是最简单的,但可能不安全(并且不能提供Open3 的所有功能); popen 更好,还有fork+exec。我不确定“IPC::Open3”是否仅表示 Linux(不知道它是否可移植),但是:在 Windows 上有用于此的 API,首先是 CreateProcess,然后是 ShellExecute(可能更多) 如果您可以使用boost,那么boost::process 可能值得一看。 【参考方案1】:

popen() 支持单向通信。如果要双向数据交换,则需要 2 个管道。 Jeff Epler 提出了以下双向 popen2.c 实现:

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

struct popen2 
    pid_t child_pid;
    int   from_child, to_child;
;

int popen2(const char *cmdline, struct popen2 *childinfo) 
    pid_t p;
    int pipe_stdin[2], pipe_stdout[2];

    if(pipe(pipe_stdin)) return -1;
    if(pipe(pipe_stdout)) return -1;

    printf("pipe_stdin[0] = %d, pipe_stdin[1] = %d\n", pipe_stdin[0], pipe_stdin[1]);
    printf("pipe_stdout[0] = %d, pipe_stdout[1] = %d\n", pipe_stdout[0], pipe_stdout[1]);

    p = fork();
    if(p < 0) return p; /* Fork failed */
    if(p == 0)  /* child */
        close(pipe_stdin[1]);
        dup2(pipe_stdin[0], 0);
        close(pipe_stdout[0]);
        dup2(pipe_stdout[1], 1);
        execl("/bin/sh", "sh", "-c", cmdline, 0);
        perror("execl"); exit(99);
    
    childinfo->child_pid = p;
    childinfo->to_child = pipe_stdin[1];
    childinfo->from_child = pipe_stdout[0];
    return 0; 


#define TESTING
#ifdef TESTING
int main(void) 
    char buf[1000];
    struct popen2 kid;
    popen2("tr a-z A-Z", &kid);
    write(kid.to_child, "testing\n", 8);
    close(kid.to_child);
    memset(buf, 0, 1000);
    read(kid.from_child, buf, 1000);
    printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0)); 
    printf("from child: %s", buf); 
    printf("waitpid() -> %d\n", waitpid(kid.child_pid, NULL, 0));
    printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0)); 
    return 0;

#endif

【讨论】:

虽然这些链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。 格哈德·巴纳德,你的意思是什么? “Try popen()”是必不可少的部分。 :) 另外,我担心 popen() 规范不会很快发生重大变化,我不相信这些链接很快就会失效。至少在“学习者”有机会点击它们之前。无论如何,我希望所包含的示例不会引发更多的刻板反应。 感谢您的提醒,但我已经知道这一点,我正在寻找的可以被认为是双向通信,比如 popen2 提供输入和输出文件描述符?我想在 C 或 CPP 中没有这样的东西 @Laszlo,我们基于 SO 条款和条件进行审查,我们不发布仅链接的答案,并且由于仅链接的答案,该帖子最初被标记为低质量。如果您随后收到 4 次删除投票,它就会被删除,这就是为什么发布评论的原因。修改后应该没问题。 @learner,是的,您需要使用 2 个管道,因为它们是单向的。

以上是关于我们在 C 或 C++ 中是不是有类似于 IPC::Open3 的 perl的主要内容,如果未能解决你的问题,请参考以下文章

Python中是不是有类似于C++ STL map的结构?

快速 java/python/C++ ipc

Java是不是有类似IPC机制的Android Handler?

在 c 程序和 C++ Qt 应用程序之间使用啥 Linux IPC?

Visual Studio 上的 IPC

IPC::Shareable 是不是适用于受祝福的对象?