C 需要有关命名管道和popen的帮助吗
我有一个小C服务器,它需要接受一个连接并派生一个子进程。我需要子进程的C 需要有关命名管道和popen的帮助吗,c,pipe,popen,C,Pipe,Popen,我有一个小C服务器,它需要接受一个连接并派生一个子进程。我需要子进程的stderr转到已经存在的命名管道,子进程的stdout转到父进程的stdout,子进程tp的stdin与父进程的stdin来自同一个位置 我最初的尝试涉及到popen(),但我似乎永远也得不到我想要的东西 最后,这个特定的解决方案只需要在Solaris中工作。谢谢 编辑:更新了这个问题,希望能更准确地描述我想要实现的目标。谢谢你对我有耐心 EDIT2:我还需要父进程获取子进程的返回值,然后对其进行处理,如果这有什么不同的话。
stderr
转到已经存在的命名管道,子进程的stdout
转到父进程的stdout
,子进程tp的stdin
与父进程的stdin
来自同一个位置
我最初的尝试涉及到popen()
,但我似乎永远也得不到我想要的东西
最后,这个特定的解决方案只需要在Solaris中工作。谢谢
编辑:更新了这个问题,希望能更准确地描述我想要实现的目标。谢谢你对我有耐心
EDIT2:我还需要父进程获取子进程的返回值,然后对其进行处理,如果这有什么不同的话。您可能使用了错误的函数-
popen()
用于调用程序写入分叉进程的标准输入或读取其标准输出。看来你两个都不想要。它还需要两个参数
您的要求也有些矛盾:
- 我希望它(理想情况下)从父级继承stdin和stdout
- 对父对象的任何输入都会返回到子对象,而子对象的任何输出都会返回到父对象
- 但至少,我希望它继承stdin并将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写入命名管道
popen()
是合适的,但“至少”的东西会让人困惑
那么,让我们来定义你真正想要的是什么
选择1