c - 管道输出的重复

标签 c

有人可以向我解释为什么我的输出中有来自 ls 命令的重复项吗? ls -l | 正常运行sort 没有给我重复的输出,所以可能是什么问题?

本质上,我试图将一个命令的输出通过管道传输到另一个命令中。该程序目前有效,但输出显示重复数据。另外,解释为什么我需要在 dup2 之后关闭将非常有帮助:)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>


// function declarations
void executeLs(int data_pipe[]);
void executeSort(int data_pipe[]);

int main(){

        int data_pipe[2]; // array storing the file descriptors
        int childls_pid; // ls child process
        int childSort_pid; // sort child process
        int rc; // return vaue of the pipe
        int child_status1;
        int child_status2;

        rc = pipe(data_pipe);
        if(rc == -1){
            perror("pipe");
            exit(1);
        }


        childls_pid = fork();
        childSort_pid = fork();

        // Ls Child process
        switch(childls_pid) {
        case -1:
                perror("fork childLs Error");
                exit(1);
        case 0:
                // inside of child process
                executeLs(data_pipe);
                exit(0);
        default:
            break;
        }

        // Sort child process
        switch(childSort_pid) {
        case -1:
                perror("fork childSort Error");
                exit(1);
        case  0:
                executeSort(data_pipe);
                exit(0);
        default:
                wait(&child_status2);
        }
        return 0;
}
void executeLs(int data_pipe[]){

    // Closes the read file descriptor
    close(data_pipe[0]);

    dup2(data_pipe[1], STDOUT_FILENO);

    // confused as to why this is necessary
    close(data_pipe[1]);

    execlp("ls", "ls", "-1", NULL);
}
void executeSort(int data_pipe[]){

    // close the write file descriptor
    close(data_pipe[1]);

    dup2(data_pipe[0], STDIN_FILENO);
    close(data_pipe[0]);
    execlp("sort","sort", NULL);
}

最佳答案

原因是您 fork 的进程比您预期的要多。当你这样做时:

    childls_pid = fork();
    childSort_pid = fork();

您正在原始父进程和第一个 fork() 创建的进程中执行第二个 fork()。所以你现在有以下进程树:

parent
    childls
        childSort
    childSort

childlschildls->childSort中,childls_pid都是0,所以它们都执行case 0: 运行 executeLs() 的子句。

您需要将第二个fork 移动到仅在原始父级中运行的代码中。您可以简单地将它移到第一个 switch 语句之后。

您需要关闭管道 FD 的原因是管道在打开它的所有进程都关闭它之前并没有真正关闭。如果子进程打开了其管道的写入端,这将阻止它读取管道上的 EOF

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

// function declarations
void executeLs(int data_pipe[]);
void executeSort(int data_pipe[]);

int main(){

    int data_pipe[2]; // array storing the file descriptors
    int childls_pid; // ls child process
    int childSort_pid; // sort child process
    int rc; // return vaue of the pipe
    int child_status1;
    int child_status2;

    rc = pipe(data_pipe);
    if(rc == -1){
        perror("pipe");
        exit(1);
    }

    childls_pid = fork();

    // Ls Child process
    switch(childls_pid) {
    case -1:
        perror("fork childLs Error");
        exit(1);
    case 0:
        // inside of child process
        executeLs(data_pipe);
        exit(0);
    default:
        break;
    }

    childSort_pid = fork();

    // Sort child process
    switch(childSort_pid) {
    case -1:
        perror("fork childSort Error");
        exit(1);
    case  0:
        executeSort(data_pipe);
        exit(0);
    default:
        wait(&child_status2);
    }
    return 0;
}

void executeLs(int data_pipe[]){

    // Closes the read file descriptor
    close(data_pipe[0]);

    dup2(data_pipe[1], STDOUT_FILENO);

    // confused as to why this is necessary
    close(data_pipe[1]);

    execlp("ls", "ls", "-1", NULL);
}

void executeSort(int data_pipe[]){

    // close the write file descriptor
    close(data_pipe[1]);

    dup2(data_pipe[0], STDIN_FILENO);
    close(data_pipe[0]);
    execlp("sort","sort", NULL);
}

关于c - 管道输出的重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33814160/

相关文章:

c - 如何使用 ifdef 检测英特尔的编译器 (ICC)?

c - 冒泡和插入之间的时间复杂度

C ECC 双相加

c++ - 不必要的 else 语句 : Is there any disadvantage to using ELSE IF when just IF can be used?

c - linux 内核系统调用服务例程的源代码在哪里?

c - 读取字符串中的字符串并计算字符串1在字符串2中出现的次数

c - 取消引用双指针

C 预处理器指针调配

iphone - 如何使用 XOR 加密音乐文件

c - 如何将 pcre2 修复为\w 将匹配标记?