如何让 wc 接受管道文件而不是标准输入来获取输入?
How to make wc accept a pipe file to take input from instead of stdin?
这是一道作业题。任务是使用 execlp
、fork
和管道复制命令:ls | wc -l
在 C 程序中。
我的方法
我觉得问题可以这样解决:
- 创建管道文件:
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
>
问题
这有两点错误:
既然我把child的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;
}
感谢您的宝贵意见。
代码中的问题是我根本没有使用管道。我正在使用我创建的文件完成所有工作。这就是基本问题。
这是新代码:
#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;
}
这是一道作业题。任务是使用 execlp
、fork
和管道复制命令:ls | wc -l
在 C 程序中。
我的方法
我觉得问题可以这样解决:
- 创建管道文件:
pipe.txt
- 使用
fork()
创建子进程- 将子进程的
stdout
映射到pipe.txt
- 使用
execlp
执行 - 这会将
ls
的输出放入pipe.txt
ls
- 将子进程的
- 父进程内部
- 将父进程的
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
>
问题
这有两点错误:
既然我把child的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;
}
感谢您的宝贵意见。
代码中的问题是我根本没有使用管道。我正在使用我创建的文件完成所有工作。这就是基本问题。
这是新代码:
#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;
}