如何使wc接受管道文件以代替stdin接受输入? [英] How to make wc accept a pipe file to take input from instead of stdin?
问题描述
这是一个作业问题.任务是复制命令: ls |使用
execlp
, fork
和管道在C程序中使用wc -l </code>.
This is a homework problem. The task is to replicate the command: ls | wc -l
in a C program using execlp
, fork
, and pipes.
我的方法
我认为可以通过以下方式解决问题:
I think the problem can be solved this way:
- 创建管道文件:
pipe.txt
- 使用
fork()
创建一个子进程- 将子进程的
stdout
映射到pipe.txt
- 使用
execlp
执行 - 这会将
ls
的输出放入pipe.txt
ls
- 将子进程的
- Create a pipe file:
pipe.txt
- Create a child process using
fork()
- Map the
stdout
of the child process topipe.txt
- Execute
ls
usingexeclp
- This puts the output of
ls
intopipe.txt
- Map the
- 将父进程的
stdin
映射到pipe.txt
- 使用
execlp
执行wc -l </code>而不给出任何其他参数,因此它从stdin读取
- 由于此父进程的
stdout
仍然是终端本身,因此它应在终端上打印出行数
- Map the
stdin
of the parent process topipe.txt
- Execute
wc -l
usingexeclp
without giving any further arguments so it reads from stdin instead - Since the
stdout
of this parent process is still the terminal itself, so it should print out the number of lines on the terminal
我的代码
#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
>
问题
与此有关的两件事是错误的:
Two things that are wrong with this:
-
由于我将孩子的标准输出设置为
pipe.txt
文件,为什么它仍在终端上输出?注意:确实会将输出也放在pipe.txt
文件中.但是为什么它也显示在终端上?
Since I set the stdout of the child to be the
pipe.txt
file, why does it still output on the terminal? NOTE: It does put the output in thepipe.txt
file too. But why does it display on the terminal too?
它开始等待用户提供输入吗?它不应该从管道文件而不是用户那里获取输入吗?
It starts waiting for the user to provide the input? Shouldn't it get the input from pipe file instead of the user?
预期产量
5
*如果当前目录中有5个文件
*if there are 5 files in the current directory
尝试过的解决方案
- 仅使用管道:(出现了错误的文件描述符错误)
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;
}
推荐答案
感谢有用的评论.
代码中的问题是我根本没有使用管道.我正在使用创建的文件进行所有工作.这就是基本问题.
The problem in the code is that I am not using pipes at all. I was doing all my work with a file that I created. So that was the basic problem.
这是新代码:
#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() {
// Step1. Create pipe file descriptors: pipefd[0] for reading from pipe, pipefd[1] for writing to the pipe
int pipefds[2];
// Helping variables
int returnstatus;
int pid;
// Step2. Create a pipe with the file descriptors
returnstatus = pipe(pipefds);
// Check if pipe was successfully created
if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}
// Step3. Fork to create a child process
pid = fork();
if (pid == 0) {
// Inside the child process
// Step4. Duplicate the file descriptor of the write end of the pipe and set it equal to the stdout of the process
dup2(pipefds[1], 1);
// Step5. Close both ends of the pipe
close(pipefds[0]);
close(pipefds[1]);
// Step6. Execute the LS command. It ouputs to stdout which we set equal to the pipe in Step4.
// So essentially, we send all output of ls to our pipe
returnstatus = execlp("ls", "ls", NULL);
// Error checking the execlp command
if (returnstatus == -1){
perror("Error executing execlp: ");
}
} else {
// Inside the parent process
// Step7. Duplicate the file descriptor the READ end of the pipe and set it equal to the stdin of the process
dup2(pipefds[0], 0);
// Step8. Close the both ends of the pipe
close(pipefds[0]);
close(pipefds[1]);
// Step9. Execute the WC command. It takes the file as an argument usually but if no file is given, it will take
// stdin as input. Since the stdin is the pipe, therefore it will read all the data from the pipe.
// The output of the wc command is stdout which is the terminal for this process so we will get the number of
// files/directories in the current directory as an output on the terminal
returnstatus = execlp("wc", "wc", "-l", NULL);
// Error checking the execlp command
if (returnstatus == -1){
perror("Error executing execlp: ");
}
}
return 0;
}
这篇关于如何使wc接受管道文件以代替stdin接受输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!