簡體   English   中英

C叉管多道工序

[英]C fork and pipe multiple process

我正在嘗試實現此命令cat /etc/passwd | grep 1000 | cut -d: -f1 cat /etc/passwd | grep 1000 | cut -d: -f1 在C中使用系統調用fork和pipe cat /etc/passwd | grep 1000 | cut -d: -f1
當我僅使用兩個命令cmd1 | cmd2 cmd1 | cmd2所以1個fork可以正常工作,但是當我使用2個以上的進程時,會出現問題
這是我的代碼,我認為問題出在Grand Parent塊中

更新
我關閉了一些未關閉的文件描述符

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


int main(){
    int fd[2], fd2[2];
    pid_t pid, pid2;
    char str[100];

    if(pipe(fd) != 0){
        fprintf(stderr, "Error pipe.\n");
        return 1;
    }
    if(pipe(fd2) != 0){
        fprintf(stderr, "Error pipe.\n");
        return 1;
    }

    do{
        pid = fork();
    }while(pid == -1 && errno == EAGAIN);

    if(pid == -1){
        perror("fork()");
        exit(1);
    }

    if(pid == 0){
        pid2 = fork();
        if(pid2 == 0){
            // fprintf(stderr, "1 - Grand Child\n");
            close(fd[0]);
            dup2(fd[1], 1);
            close(fd[1]);
            execlp("cat", "cat", "/etc/passwd", NULL);
            perror("cat error");
        }else{
            wait(&pid2);
            // fprintf(stderr, "2 - Child\n");
            close(fd[1]);
            dup2(fd[0], 0);
            close(fd[0]);

            up2(fd2[1], 1);
            close(fd2[1]);

            execlp("grep", "grep", "1000", NULL);
            perror("grep failed");
        }
        return 1;
    }else{
        wait(&pid);
        // fprintf(stderr, "3 - Parent\n");
        close(fd[0]);
        dup2(fd2[0], 0);
        close(fd2[0]);
        execlp("cut", "cut", "-d:", "-f1", NULL);
        perror("cut failed");
        return 1;
    }
    return 0;
}

您需要關閉孩子和父母中所有未使用的文件描述符! 在這種情況下,使用dup2()時,可能會關閉與管道關聯的所有文件描述符。

為了清楚起見,我將宏用於與stdin和stdout相關的文件描述符。 宏STDIN_FILENO和STDOUT_FILENO在unistd.h中聲明。

不需要等待孩子( wait(&pid);wait(&pid2); )。 您無需等待cat結束即可運行grep ,因為grep會在它們出現時對其進行處理。 管道應具有較大的緩沖區,如65536字節,因此在cat命令結束后,數據將在管道中進行緩沖,但這並不是值得依靠的。

以下代碼僅需進行少量更改即可起作用:

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

int main(){
    int fd[2], fd2[2];
    pid_t pid, pid2;
    char str[100];

    if(pipe(fd) != 0){
        fprintf(stderr, "Error pipe.\n");
        return 1;
    }
    if(pipe(fd2) != 0){
        fprintf(stderr, "Error pipe.\n");
        return 1;
    }

    do{
        pid = fork();
    }while(pid == -1 && errno == EAGAIN);

    if(pid == -1){
        perror("fork()");
        exit(1);
    }

    if(pid == 0){
        pid2 = fork();
        if(pid2 == 0){
            // fprintf(stderr, "1 - Grand Child\n");
            dup2(fd[1], STDOUT_FILENO); // 1);
            close(fd[0]);
            close(fd[1]);
            close(fd2[1]);
            close(fd2[0]);

            execlp("cat", "cat", "/etc/passwd", NULL);
            perror("cat error");
        }else{
            // wait(&pid2);
            // fprintf(stderr, "2 - Child\n");
            dup2(fd[0], STDIN_FILENO); //0);
            dup2(fd2[1], STDOUT_FILENO); // 1);
            close(fd[0]);
            close(fd[1]);
            close(fd2[1]);
            close(fd2[0]);

            execlp("grep", "grep", "1000", NULL);
            perror("grep failed");
        }
        return 1;
    }else{
        // wait(&pid);
        // fprintf(stderr, "3 - Parent\n");
        dup2(fd2[0], STDIN_FILENO); //0);
        close(fd[0]);
        close(fd[1]);
        close(fd2[1]);
        close(fd2[0]);

        execlp("cut", "cut", "-d:", "-f1", NULL);
        perror("cut failed");
        return 1;
    }
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM