簡體   English   中英

執行 ls | wc linux 命令在 c 程序中使用 2 個進程通過 pipe 進行通信

[英]Executing the ls | wc linux command in c program using 2 processes communicating trough a pipe

我目前在以下練習中遇到問題:

我想“模仿” pipe 命令行ls | wc ls | wc在 linux bash 中使用以下程序。 我要做的是:

  • 創建一個 pipe
  • 創建一個 reader child 和 writer child
  • writer child 關閉管道的讀取端並將他的標准輸出重定向到 pipe 的寫入端
  • 讀者孩子關閉管道的寫入端並使 pipe 的讀取端成為標准輸入
  • 兩個孩子都執行 exec,編寫器執行ls程序,將 output 通過 pipe 傳遞給在該 Z78E6221F6393D1356681DB398F14CED6 上執行wc程序的讀取器

當我做ls | wc ls | wc在 linux 終端我得到以下結果:

8      8     101

但是如果我執行我的程序,我會得到以下結果:

0      0      0

這是我的程序:

#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h>
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <string.h> 
#include <sys/wait.h>
#include <libgen.h>
#include <signal.h>
#include <errno.h>

int main(void){
        int mypipe[2];
        pid_t pid1, pid2;

        if (pipe(mypipe)<0)
                perror ("pipe error"), exit(1);
        if ((pid1=fork())<0)
                perror ("fork error"), exit(1);

        else if (pid1==0) {
                //reader child
                close (mypipe[1]);
                if (dup2(mypipe[0], STDIN_FILENO)!=STDIN_FILENO)
                        perror ("dup2 error"), exit(1);
                close (mypipe[0]); 
                if (execlp("wc", "wc", NULL)<0)
                        perror("execlp1 error"), exit(1);
                else {  //pid >0, parent
                        if ((pid2=fork())<0)
                                perror ("fork error"), exit(2);
                        else if (pid2==0) {     
                                //writer child
                                close(mypipe[0]);
                                if (dup2(mypipe[1], STDOUT_FILENO) != STDOUT_FILENO)
                                        perror("dup2 error"), exit(1);
                                close (mypipe[1]);
                                if (execlp("ls", "ls", NULL)<0)
                                        perror ("execlp error"), exit(1);
                        }
                        else {  //parent
                                close(mypipe[0]);
                                close(mypipe[1]);

                                waitpid(pid1, NULL, 0);
                                waitpid(pid2, NULL, 0);
                                exit(0);
                        }
                }
        }
return 0;
}

我究竟做錯了什么? 提前感謝您的回答!

你的代碼很混亂。 您有許多不相關的標題,並重復#include <errno.h> main() function 中,您有:

int main(void)
{
    int mypipe[2];
    pid_t pid1, pid2;

    if (pipe(mypipe) < 0)
        perror("pipe error"), exit(1);
    if ((pid1 = fork()) < 0)
        perror("fork error"), exit(1);
    else if (pid1 == 0)
    {   
        // reader child
        close(mypipe[1]);
        if (dup2(mypipe[0], STDIN_FILENO) != STDIN_FILENO)
            perror("dup2 error"), exit(1);
        close(mypipe[0]);
        if (execlp("wc", "wc", NULL) < 0)
            perror("execlp1 error"), exit(1);
        else            // pid >0, parent
        {   
            …
        }
    }
    return 0;
}

else if (pid1 == 0)子句由子執行。 它關閉 pipe 的寫入端,將讀取端復制到標准輸入並關閉 pipe 的讀取端。 然后它在wc上執行execlp() 只有當代碼執行wc失敗時才會執行else子句,然后只有 pipe 的讀取端保持打開狀態。 同時,原始進程簡單地退出。 這將關閉 pipe,因此wc命令沒有輸入,並報告0 0 0作為結果。

你需要重寫代碼。 父進程應該等到它的兩個子進程都執行。 尤其是在調試的時候,千萬不要忽略children的退出狀態,要上報。

這是一些有效的代碼。 請注意,它避免了濃密的決策樹——它是if / else if / ... / else代碼的線性序列。 一般來說,這比一組復雜的、多層次的條件更容易理解。

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

int main(void)
{
    int fd[2];
    pid_t pid1, pid2;

    if (pipe(fd) < 0)
        perror("pipe error"), exit(1);
    else if ((pid1 = fork()) < 0)
        perror("fork error"), exit(1);
    else if (pid1 == 0)
    {
        /* ls */
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        execlp("ls", "ls", (char *)0);
        perror("exec ls");
        exit(1);
    }
    else if ((pid2 = fork()) < 0)
        perror("fork error"), exit(1);
    else if (pid2 == 0)
    {
        /* wc */
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        execlp("wc", "wc", (char *)0);
        perror("exec wc");
        exit(1);
    }
    else
    {
        close(fd[0]);
        close(fd[1]);
        int status1;
        int status2;
        int corpse1 = waitpid(pid1, &status1, 0);
        int corpse2 = waitpid(pid2, &status2, 0);
        printf("ls: pid = %d, corpse = %d, exit status = 0x%.4X\n", pid1, corpse1, status1);
        printf("ls: pid = %d, corpse = %d, exit status = 0x%.4X\n", pid2, corpse2, status2);
    }
    return 0;
}

在我的機器上運行程序pipe41的示例生成:

$ pipe41
     175     175    1954
ls: pid = 44770, corpse = 44770, exit status = 0x0000
ls: pid = 44771, corpse = 44771, exit status = 0x0000
$ ls | wc
     175     175    1954
$

暫無
暫無

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

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