2011-11-26 88 views
1

我試圖實現一個支持多個管道的簡單shell程序。現在我的shell可以實現一些簡單的內置命令和外部命令。我通過從空格" "分隔的命令行獲取用戶輸入,並將每個字符串放在char* argv[]中。現在的問題是執行管道。我在這個鏈接http://www.cs.loyola.edu/~jglenn/702/S2005/Examples/dup2.html上讀了一篇關於它的文章。我明白它是如何工作的。在Linux Shell中使用C實現管道使用C

所以我想每次約strcmpargv[i]"|",我所遇到的管道,我fork一個新的進程。然後我把管子放在char* argv[]之前的管子和另一個char* argv[]的管子之後。這可能適用於1管道,但如果用戶輸入多個管道有多個管道,事情可能會用這種方法乏味。我的主要問題是關於分離管道兩端的字符串。關於如何實現它的任何想法?謝謝。

回答

2

分而治之:

  1. 查找第一管參數
  2. 如果沒有找到配管,作爲輸出與標準輸出執行所述陣列和終止。
  3. 在非管道第一部分和其他部分之間劃分參數數組。
  4. 做一個管和與該管作爲輸出執行非管第一部分
  5. 卸下非管的第一部分和從所述參數數組管道
  6. 轉到第1

步驟3是由於至C數組的語義,很簡單:

char **arguments; 
int pipe_position = /* for example: */ 5; 
assert(strcmp(arguments[pipe_position], "|") == 0); 
arguments[pipe_position] = NULL; 
char **my_arguments = arguments; 
arguments = arguments + pipe_position + 1; 

然後my_arguments是長度包含第一參數pipe_position的陣列,並且arguments是一個數組包含其餘的長度爲argc - pipe_position - 1。您可以將這些指針指向execvp,而不會出現問題。是的,他們指向相同的內存塊,但這不是execvp關心的問題。

+0

謝謝您的回覆。第3號是我的問題所在。如何將'char * []'類型的參數數組劃分爲另一個'char * []'的數組?如果我有多個管道,是否必須爲遇到的每個管道連續創建一個數組?我使用execvp來執行參數數組。 – mkab

+0

@mkab:據此編輯。 – thiton

+0

我想我會把握一點。所以這個分而治之的方法應該在while [i]!= NULL'的時候完成。我對嗎?我也應該這樣調用execvp:'execvp(* my_arguments,my_arguments)'而不是'execvp(* my_arguments,arguments)'? – mkab

2

您甚至可以通過用空字符串替換管道(終止argv數組)來重用argv數組。

所以你的陣列是這樣的:

"a", "b", "|", "c", "d", "e", "|", "f", "g", "h", NULL 

你變成

"a", "b", NULL, "c", "d", "e", NULL, "f", "g", "h", NULL 

,瞧,這裏有你的三個命令行:argvargv+3argv+7

的使用管道的困難部分是設置stdin和stdout文件描述符,而不是命令的實際執行。

+0

感謝您的回覆。我想我有點理解它。我使用execvp來執行我的命令。那麼我需要爲每個以NULL結尾的字符串創建一個單獨的數組嗎?例如'array1 =「a」,「b」,NULL'' array2 =「c」,「d」,「e」,NULL'' array3 =「f」,「g」,「h」,NULL' – mkab

+0

不,你沒有。您現在可以使用子數組,因爲它們是NULL終止的。 –

+0

感謝您的幫助。幫助我澄清一些事情。 – mkab