簡體   English   中英

ls | wc使用C不起作用

[英]ls | wc using C doesn't work

我寫了一個C程序,它使用多個管道來模擬shell。 問題是我可以運行大多數命令,如ls | cat ls | cat等,但我無法使用ls | wc ls | wc 什么情況下wc不起作用?

int pipefd[4]; 
int p1 = pipe(pipefd);          // Open pipe 1
int p2 = pipe(pipefd + 2);      // Open pipe 2

pid_t pid;

for(i = 0; i < n_commands; i++)
{
    fflush(stdout);
    pid = fork();

    if(pid == 0)
    {
        int command_no = i;
        int prev_pipe = ((command_no - 1) % 2) * 2;
        int current_pipe = (command_no % 2) * 2;

        // If current command is the first command, close the
        // read end, else read from the last command's pipe
        if(command_no == 0)
        {
            close(pipefd[0]);
        }
        else
        {
            dup2(pipefd[prev_pipe], 0);
            close(pipefd[current_pipe]);
        }

        // If current command is the last command, close the
        // write end, else write to the pipe
        if(command_no == n_commands - 1)
        {
            close(pipefd[current_pipe + 1]);
        }
        else
        {
            dup2(pipefd[current_pipe + 1], 1);
        }

        int p = execvp(tokens[cmd_pos[command_no]], tokens + cmd_pos[command_no]);

        close(pipefd[current_pipe]);
        close(pipefd[prev_pipe]);
        close(pipefd[prev_pipe + 1]);
        close(pipefd[current_pipe + 1]);

        _exit(0);
    }
}

如果它們不是管道中的第一個命令,那么/usr/bin中的程序似乎沒有被執行。

您錯誤地連接了管道。

這個邏輯:

int prev_pipe = ((command_no - 1) % 2) * 2;
int current_pipe = (command_no % 2) * 2;

不起作用 - 模數的結果將始終為01 ,因此prev_pipecurrent_pipe將為02 ...

好吧,除非我錯過了一些隱藏的概念,因為你沒有粘貼創建管道的任何代碼。

這是一個從您的代碼創建的非常簡單的程序 - 猜測如何創建管道並簡化命令argv處理:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static char *argv_ls[] = { "ls", 0 };
static char *argv_wc[] = { "wc", 0 };
static char **cmds[]   = { argv_ls, argv_wc };

int main(void)
{
    int n_commands = 2;
    int pipefd[2];

    pipe(&pipefd[0]);   // Error check!

    fflush(stdout);
    for (int i = 0; i < n_commands; i++)
    {
        int pid = fork();

        if (pid == 0)
        {
            int command_no = i;
            int prev_pipe = ((command_no - 1) % 2) * 2;
            int current_pipe = (command_no % 2) * 2;
            printf("cmd %d: prev pipe %d, curr pipe %d\n", i, prev_pipe, current_pipe);
            fflush(stdout);

            // If current command is the first command, close the
            // read end, else read from the last command's pipe
            if (command_no == 0)
            {
                close(pipefd[0]);
            }
            else
            {
                dup2(pipefd[prev_pipe], 0);
                close(pipefd[current_pipe]);  // Line 40
            }

            // If current command is the last command, close the
            // write end, else write to the pipe
            if (command_no == n_commands - 1)
                close(pipefd[current_pipe + 1]);  // Line 46
            else
                dup2(pipefd[current_pipe + 1], 1);

            execvp(cmds[i][0], cmds[i]);
            fprintf(stderr, "Failed to exec: %s (%d: %s)\n", cmds[i][0], errno, strerror(errno));
            _exit(1);
        }
    }

    return 0;
}

當GCC 4.7.1(在Mac OS X 10.7.4上)編譯它時,它會發出警告:

pipes-12133858.c: In function ‘main’:
pipes-12133858.c:40:22: warning: array subscript is above array bounds [-Warray-bounds]
pipes-12133858.c:46:22: warning: array subscript is above array bounds [-Warray-bounds]

當我運行它時,我得到輸出:

Isis JL: pipes-12133858
cmd 0: prev pipe -2, curr pipe 0
cmd 1: prev pipe 0, curr pipe 2
Isis JL: wc: stdin: read: Bad file descriptor

由於代碼中的父級不等待子級完成,因此提示出現在來自wc的錯誤消息之前,但是打印的診斷編號顯示存在各種問題(編譯器能夠發現一些問題) )。

請注意,無需檢查任何exec*()系列函數的返回值。 如果他們成功了,他們就不會回來; 如果他們回來,他們就失敗了。 在調用_exit(0);之前也沒有必要關閉_exit(0); 因為系統無論如何都會關閉它們。 此外,當您未能執行某些操作時,打印一條指示您未能執行的消息並以非零退出狀態退出是有禮貌的。

因此,正如MichałGórny所說,問題的一個主要部分是你的管道處理代碼至少是神秘的,因為你沒有顯示它並且可能是錯誤的。

我也很容易確定你的代碼中沒有足夠的close()調用。 作為指導原則,在管道中打開管道的每個進程中, pipe()系統調用返回的所有文件描述符都應該在任何給定子進程使用exec*()函數之前關閉。 。 不關閉管道會導致進程掛起,因為管道的寫入端已打開。 如果打開寫入結束的進程是嘗試從管道的讀取端讀取的進程,那么它將不會找到要讀取的任何數據。

暫無
暫無

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

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