【发布时间】:2020-02-27 17:25:39
【问题描述】:
这是一道作业题。任务是使用 execlp、fork 和管道在 C 程序中复制命令:ls | wc -l。
我的方法
我觉得问题可以这样解决:
- 创建管道文件:
pipe.txt - 使用
fork()创建子进程- 将子进程的
stdout映射到pipe.txt - 使用
execlp执行ls - 这会将
ls的输出放入pipe.txt
- 将子进程的
- 父进程内部
- 将父进程的
stdin映射到pipe.txt - 使用
execlp执行wc -l而不提供任何进一步的参数,因此它改为从标准输入读取 - 由于这个父进程的
stdout还是终端本身,所以应该打印出终端的行数
- 将父进程的
我的代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
int main() {
int pipefds[2];
int returnstatus;
int pid;
char argArr[30] = {'\n'};
returnstatus = pipe(pipefds);
if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}
int file_desc = open("pipe.txt", O_RDWR | O_APPEND | O_CREAT);
pid = fork();
if (pid == 0) {
int copy_desc = dup2(file_desc, 1);
execlp("ls", "ls", NULL);
} else {
int copy_desc = dup2(file_desc, 0);
close(copy_desc);
execlp("wc", "wc", "-l", NULL);
}
return 0;
}
实际输出
main.cpp blabla.cpp main pipe.txt
>
问题
这有两个问题:
既然我把孩子的stdout设置为
pipe.txt文件,为什么还在终端上输出呢?注意:它也将输出放在pipe.txt文件中。但是为什么终端也会显示呢?它开始等待用户提供输入?它不应该从管道文件而不是用户获取输入吗?
预期输出
5
*如果当前目录有5个文件
尝试过的解决方案
- 仅使用管道:(遇到错误的文件描述符错误)
int main() {
int pipefds[2];
int returnstatus;
int pid;
returnstatus = pipe(pipefds);
if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}
pid = fork();
if (pid == 0) {
dup2(pipefds[0], 1);
close(pipefds[1]);
execlp("ls", "ls", NULL);
} else {
dup2(pipefds[1], 0);
close(pipefds[0]);
execlp("wc", "wc", "-l", NULL);
}
return 0;
}
【问题讨论】:
-
一个文件“pipe.txt”不是管道,你应该使用
pipe函数,见man pipe。 -
我刚刚注意到你的程序包含
returnstatus = pipe(pipefds);,但你没有使用pipefds。 -
@kronaemmanuel 管道有两个末端:一个可以从 (pipefds[0]) 读取的末端和一个可以写入 (pipefds[1]) 的末端,并且您的程序以错误的方式获取它们.
-
@kronaemmanuel 是的,还有很多需要关闭。样板代码是
dup2(pipefds[0], x); close(pipefds[0]); close(pipefds[1]);..关闭它们。您要保留的已被复制,现在您有两个,其中一个应该关闭。