C 需要有关命名管道和popen的帮助吗

C 需要有关命名管道和popen的帮助吗,c,pipe,popen,C,Pipe,Popen,我有一个小C服务器,它需要接受一个连接并派生一个子进程。我需要子进程的stderr转到已经存在的命名管道,子进程的stdout转到父进程的stdout,子进程tp的stdin与父进程的stdin来自同一个位置 我最初的尝试涉及到popen(),但我似乎永远也得不到我想要的东西 最后,这个特定的解决方案只需要在Solaris中工作。谢谢 编辑:更新了这个问题,希望能更准确地描述我想要实现的目标。谢谢你对我有耐心 EDIT2:我还需要父进程获取子进程的返回值,然后对其进行处理,如果这有什么不同的话。

我有一个小C服务器,它需要接受一个连接并派生一个子进程。我需要子进程的
stderr
转到已经存在的命名管道,子进程的
stdout
转到父进程的
stdout
,子进程tp的
stdin
与父进程的
stdin
来自同一个位置

我最初的尝试涉及到
popen()
,但我似乎永远也得不到我想要的东西

最后,这个特定的解决方案只需要在Solaris中工作。谢谢

编辑:更新了这个问题,希望能更准确地描述我想要实现的目标。谢谢你对我有耐心


EDIT2:我还需要父进程获取子进程的返回值,然后对其进行处理,如果这有什么不同的话。

您可能使用了错误的函数-
popen()
用于调用程序写入分叉进程的标准输入或读取其标准输出。看来你两个都不想要。它还需要两个参数

您的要求也有些矛盾:

  • 我希望它(理想情况下)从父级继承stdin和stdout

  • 对父对象的任何输入都会返回到子对象,而子对象的任何输出都会返回到父对象

  • 但至少,我希望它继承stdin并将stdout写入命名管道

第一个选项很简单-它不需要特殊编码。提供给父进程的stdin的任何数据也将在子进程的stdin上可用(但只有两个进程中的一个进程可以读取它)。孩子的stdout通常与父母的stdout放在同一个地方。如果您想让家长阅读孩子的标准输出,那么您确实需要一个管道,
popen()
是合适的,但是“至少”的内容令人困惑

那么,让我们来定义你真正想要的是什么

选择1
  • 子级的标准错误应转到命名管道
  • 调用进程应该读取子进程的标准输出
  • 子项的标准输入应来自与父项的标准输入相同的位置
  • 命名管道已存在
  • 因此:

    FILE *fp = popen("/run/my/command -with arguments 2>/my/other/pipe", "r");
    
    注意,子进程将被挂起,直到进程打开“/my/other/pipe”进行读取;这反过来意味着,如果父进程从
    fp
    读取,它也将被挂起,直到其他进程打开“/my/other/pipe”进行读取

    选择2
  • 子级的标准错误应转到命名管道
  • 子级的标准输出应转到父级的标准输出
  • 子项的标准输入应来自与父项的标准输入相同的位置
  • 命名管道已存在
  • 现在
    popen()
    是不合适的,我们进入了赤裸裸的“fork&exec”代码。下面是比操作C更多的伪代码

    if ((pid = fork() < 0)
        error
    else if (pid > 0)
    {
        /* Parent - might wait for child to complete */
    }
    else
    {
        int fd = open("/my/other/pipe", O_WRONLY|O_NONBLOCK);
        if (fd < 0)
            error
        dup2(fd, 2);  /* There is a symbolic name for stderr too */
        close(fd);    /* Do not want this open any more */
        char *cmd[4] = { "/bin/sh", "-c", "/run/my/command -with arguments", 0 };
        execv(cmd[0], cmd);
        error - if execv returns, it failed!
    }
    
    if((pid=fork()<0)
    错误
    否则,如果(pid>0)
    {
    /*父级-可能等待子级完成*/
    }
    其他的
    {
    int fd=打开(“/my/other/pipe”,O_WRONLY | O_NONBLOCK);
    如果(fd<0)
    错误
    dup2(fd,2);/*stderr也有一个符号名*/
    关闭(fd);/*不想再打开此窗口*/
    char*cmd[4]=“bin/sh”、“-c”、“/run/my/command-with-arguments”,0};
    execv(cmd[0],cmd);
    错误-如果execv返回,则失败!
    }
    
    如果您完全相信没有人会像关闭stdout那样对您施展任何特技,您可以通过在调用
    open()
    之前关闭stderr(fd=2)来避免使用
    dup2()
    。但是,如果您这样做,您就不能再报告任何错误了-因为您关闭了stderr。因此,我将按图所示进行操作

    如果您有不同的要求,请说明您想要实现的目标


    正如p2vb所指出的,如果您想让父对象等待子对象完成,那么简单地使用
    system()
    就足够了。如果在子对象运行时父对象应该继续,您可以尝试
    system()
    ,其中命令字符串以一个符号(
    &
    )结尾将子对象置于背景中,或者您可以使用上面选项2中概述的代码

    使用
    system()
    ,父级几乎没有机会读取从子级获取标准错误的/my/other/管道。如果子级产生大量错误,则很容易死锁


    另外,要小心使用FD_CLOEXEC标志-在您不希望孩子修改的文件上设置它。在Linux上,您可以在
    open()
    调用上使用O_CLOEXEC标志;在Solaris上,您必须通过
    fcntl()
    小心地设置它。

    您可能使用了错误的函数-
    popen()
    用于希望调用程序写入分叉进程的标准输入或读取其标准输出的情况。这两种情况似乎都不需要。它还需要两个参数

    您的要求也有些矛盾:

    • 我希望它(理想情况下)从父级继承stdin和stdout

    • 对父对象的任何输入都会返回到子对象,而子对象的任何输出都会返回到父对象

    • 但至少,我希望它继承stdin并将stdout写入命名管道

    第一个选项很简单-它不需要特殊编码。提供给父级stdin的任何数据也将在子级stdin上可用(但两个进程中只有一个进程可以读取)。孩子的stdout通常会与家长的stdout放在同一个位置。如果你想让家长阅读孩子的stdout,那么你确实需要一个管道,
    popen()
    是合适的,但“至少”的东西会让人困惑

    那么,让我们来定义你真正想要的是什么

    选择1
  • 子级的标准错误应转到命名管道
  • chi的标准输出