如何使wc接受管道文件以代替stdin接受输入? [英] How to make wc accept a pipe file to take input from instead of stdin?

查看:44
本文介绍了如何使wc接受管道文件以代替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:

  1. 创建管道文件: pipe.txt
  2. 使用 fork()创建一个子进程
    • 将子进程的 stdout 映射到 pipe.txt
    • 使用 execlp
    • 执行 ls
    • 这会将 ls 的输出放入 pipe.txt
  1. Create a pipe file: pipe.txt
  2. Create a child process using fork()
    • Map the stdout of the child process to pipe.txt
    • Execute ls using execlp
    • This puts the output of ls into pipe.txt
  • 将父进程的 stdin 映射到 pipe.txt
  • 使用 execlp 执行 wc -l <​​/code>而不给出任何其他参数,因此它从stdin读取
  • 由于此父进程的 stdout 仍然是终端本身,因此它应在终端上打印出行数
  • Map the stdin of the parent process to pipe.txt
  • Execute wc -l using execlp 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:

  1. 由于我将孩子的标准输出设置为 pipe.txt 文件,为什么它仍在终端上输出?注意:确实会将输出也放在 pipe.txt 文件中.但是为什么它也显示在终端上?

  1. 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 the pipe.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

尝试过的解决方案

  1. 仅使用管道:(出现了错误的文件描述符错误)

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆