使用C在Linux Shell中实现管道

时间:2011-11-26 13:01:03

标签: c linux shell char pipe

我正在尝试实现一个支持多个管道的简单shell程序。现在我的shell可以实现一些简单的内置命令和外部命令。我通过从命令行获取用户输入来完成此操作,命令行由空格" "分隔并将每个字符串放在char* argv[]中。现在的问题是执行管道。我在这个链接http://www.cs.loyola.edu/~jglenn/702/S2005/Examples/dup2.html中读了一篇关于它的文章。我明白它是如何运作的。

所以我考虑strcmp每个argv[i]"|",当我遇到管道时,我fork一个新流程。然后我将字符串放在管道前面char* argv[]中,将管道后面的字符串放在另一个char* argv[]中。这可能适用于1个管道但如果用户输入的多个管道有多个管道,则此方法可能会变得繁琐。我的主要问题是分离管道两端的琴弦。关于如何实现它的任何想法?感谢。

2 个答案:

答案 0 :(得分:2)

分而治之:

  1. 找到第一个管道参数
  2. 如果未找到管道,请使用stdout作为输出执行数组并终止。
  3. 在非管道第一部分和其余部分之间划分参数数组。
  4. 制作管道并以管道作为输出执行非管道第一部分
  5. 从参数数组
  6. 中删除非管道第一部分和管道
  7. 转到1
  8. 由于C数组语义,第3步非常简单:

    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的关注。

答案 1 :(得分: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文件描述符,而不是命令的实际执行。