2016-11-19 30 views
-1

我想寫一個簡單的shell可以處理管道命令。我希望能夠處理所有鏈接在一起的多個管道,但我很難弄清楚如何實現這樣的事情。如何鏈接多個管道? (加上奇怪的buggs)

這是我的當前的嘗試:

int status; 
    int lastToken = 0; 
    int pipe_pid; 

    //create the pipes 
    int pipefd[pipes][2]; 

    // Loop to run all commands in the vertical list. 
    while(1){ 
     if (c->type == TOKEN_PIPE){ 

     // Here is where we deal with pipes 
      for (int i = 0; i < pipes; i++){ 
       pipe(pipefd[i]); 

       pipe_pid = fork(); 

       //this is a receiving pipe 
       if (pipe_pid == 0){ 
        // create the write end of the pipe 
        dup2(pipefd[i][WRITE_SIDE], STDOUT_FILENO); 
        close(pipefd[i][READ_SIDE]); 
        close(pipefd[i][WRITE_SIDE]); 
        execvp(c->argv[0], c->argv); 
        // printf("parent pipe\n"); 
       } 
       //this is a writing pipe 
       else{ 
        close(pipefd[i][WRITE_SIDE]); 
        dup2(pipefd[i][READ_SIDE], STDIN_FILENO); 
        close(pipefd[i][READ_SIDE]); 
        // printf("child pipe\n"); 
       } 
      } 



     // This stuff happens for all commands 
     lastToken = c->type; 
     // If it's the last command, we're done 
     if (c->next == NULL){ 
      break; 
     } 
     else{ 
      c = c->next; 
     } 
    } 

命令被鏈接在一起的鏈接列表,c是我的命令指針

管,是我創建一個變量作爲我解析在串,所以我知道有多少'|'我在命令中看到。這應該告訴我需要fork的子進程的數量。

我使用管道爲管道描述符創建一個2d數組。

然後我想循環管道和叉一次爲每個,並使用dup2來映射輸入和輸出。

我得到不一致的錯誤,我找不出來。首先,每次我運行一個管道命令,我的shell立即崩潰,沒有段錯誤或其他打印錯誤。第二,如果我運行像echo foo | wc -c這樣的命令,我有時會得到4,有時得到0作爲輸出。

我敢肯定,我只是在做一些愚蠢的,但我不知道是什麼:/

+0

想想你正在做什麼 - 對於'n'過程,你需要在它們之間有'n-1'管道。你正在創建'n'進程和'n'管道,所以你有一個額外的管道。 –

+0

@ChrisDodd我認爲我實際上有n-1個進程,我決定'pipes'的值的方法是計算'|'令牌,所以它應該是正確的... – Indigo

回答

0

我想通了,我在做什麼錯了,我被關管道之前,所有線程都使用完。我通過拉出關閉電話來修復它。

// writing side of the pipe 
if (c->type == TOKEN_PIPE){ 
    close(c->pipefd[READ_SIDE]); 
    dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO); 

} 
// receiving side of the pipe 
if (commandPrev->type == TOKEN_PIPE){ 
    close(commandPrev->pipefd[WRITE_SIDE]); 
    dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO); 

} 

然後在父線程,之前,我雷普我的殭屍,我檢查是否有完成使用,並關閉其管道。

// writing side of the pipe 
    if (c->type == TOKEN_PIPE){ 
     close(c->pipefd[READ_SIDE]); 
     dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO); 
    } 
    // receiving side of the pipe 
    if (commandPrev->type == TOKEN_PIPE){ 
     close(commandPrev->pipefd[WRITE_SIDE]); 
     dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO); 
    close(commandPrev->pipefd[READ_SIDE]); 

我不確定這是否是最佳的方式來做到這一點,但它對我來說沒有任何錯誤。