【发布时间】:2019-07-28 21:28:10
【问题描述】:
我们的作业需要使用 pipe()、fork()、execve() 和 dup() 来实现一个简单的使用管道执行终端命令。所以我阅读了 dup 和 pipe 如何操作文件描述符,并生成了下面的代码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pfds[2];
pipe(pfds);
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
char *k = {"echo", "one", "two", "three", NULL};
execve("/bin/echo", k, NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
char *k = {"wc", "-w", NULL};
execve("/usr/bin/wc", k, NULL);
}
return 0;
}
运行代码似乎没有任何结果,我不确定我还需要什么才能使其工作。
我期待输出 3,正如您通过输入看到的那样
echo one two three | wc -w 在终端中。顺便说一下,我使用的是 MacOS。
【问题讨论】:
-
1) 你甚至不应该尝试关闭 1 和 0。2) 你使用 dup 函数和管道输出是不对的。最好阅读手册页以获得完整的解释,但想法是创建一个“管道”,您的程序将与 pipe() 一起使用。 fork 的父级将在此管道的一侧写入,子级将在另一侧读取。然后,您需要复制管道入口/出口的 1 或 0(取决于)。最后不要忘记关闭您不使用的管道部分(仅在父/子分隔的代码中,不要在主要部分中关闭两者,否则什么都不起作用B-))
-
请注意,您将执行的程序传递给一个空环境。那不是你应该做的。要么传入自定义环境,要么使用进程自己的环境(在任何函数之外使用
extern char **environ;——这未在任何 POSIX 标头中声明——然后使用environ作为execve()的第三个参数,或者使用execv()而不是execve(),因为你不是在修补环境。 -
@Angevil dup 的使用似乎几乎正确但丑陋 - 应该使用 dup2 代替
-
@AnttiHaapala 你对这个警告是对的,如果我看一下,我本可以找出问题所在。我不确定您所说的“dup 几乎正确但丑陋”是什么意思,您能分享更多信息吗?
-
@AnttiHaapala 事实上,这段代码在这种情况下并不健壮,但除非提问者以一种奇怪的方式运行程序,否则在她/他运行它时不应该阻止它工作。跨度>
标签: c pipe system-calls execve