在自定义linux shell中管道

时间:2013-07-10 01:05:18

标签: c linux pipe

尝试使用一些基本功能实现我自己的linux shell,当然,在实现管道时会出现问题。更具体地说,管道在很大程度上起作用,尽管它似乎放弃了最后一个论点。例如,如果我要运行命令

ps ax | grep ps

在我的shell中删除grep命令后的ps。因此,不要使用典型的Linux shell

输出
339 ?        S      0:00 upstart-udev-bridge --daemon
497 ?        Ss     0:00 /usr/sbin/cupsd -F
503 ?        S<     0:00 [kpsmoused]
720 ?        S      0:00 upstart-socket-bridge --daemon
5541 pts/0    R+     0:00 ps ax
5542 pts/0    S+     0:00 grep --colour=auto ps

你得到了这个

339 ?        S      0:00 upstart-udev-bridge --daemon
497 ?        Ss     0:00 /usr/sbin/cupsd -F
503 ?        S<     0:00 [kpsmoused]
720 ?        S      0:00 upstart-socket-bridge --daemon
5557 pts/0    R+     0:00 ps ax

在这种情况下,您不会搜索匹配的模式ps。

管道功能如下

void mypipes(char* args[], int nargs)
{
  pid_t pid;
  int fd[2];

  char* cmdargs[nargs - 2];
  char* cmdargs2[nargs - 2];


  int i;
  int t = 0;
  int count = 0;

  for(i = 0; i < nargs; i++)
  {
if(!strcmp(args[i], "|"))
{
    //dont put into array
    t = 1;
}
else if(t == 0)
{
    cmdargs[i] = args[i];
    count++;
}
else if(t == 1)
{
    cmdargs2[i - 3] = args[i];
}
  }


  if(count == 2)
  {
  pipe(fd);
  pid = fork();

  if(pid == -1)
  { 
    perror("unable to fork");
    exit(1);
  }
  if(pid > 0)
  {
    wait(&pid);
    close(fd[1]);
    close(0);
    dup2(fd[0],0);
    execlp(cmdargs2[0], cmdargs2[0], cmdargs2[1], NULL);
  }
  if(pid == 0)
  {
    close(fd[0]);
    close(1);
    dup2(fd[1],1);
    execlp(cmdargs[0], cmdargs[0], cmdargs[1], NULL);
  }
  }

  if(count == 1)
  {
  pipe(fd);
  pid = fork();

  if(pid == -1)
  { 
    perror("unable to fork");
    exit(1);
  }
  if(pid > 0)
  {
    wait(&pid);
    close(fd[1]);
    close(0);
    dup2(fd[0],0);
    execlp(cmdargs2[0], cmdargs2[1], NULL);
  }
  if(pid == 0)
  {
    close(fd[0]);
    close(1);
    dup2(fd[1],1);
    execlp(cmdargs[0], cmdargs[1], NULL);
  }

  }

}

我已经检查过管道后面的所有变量是否仍然在第二组参数内并且它们是问题不是主要的但是在某处我正在执行它不读取的实际管道到最后。

提前感谢您提供有关此处可能出现的错误的任何提示。

1 个答案:

答案 0 :(得分:1)

首先,除非我遗漏了一些东西,否则你的两个样本输出看起来都像是在工作:它们都只列出了带有“ps”的行。 (如果它确实在运行ps ax | grep,则grep会抱怨使用情况)。我在输出中看到的唯一区别是第二个没有列出grep进程本身,但如果ps已经完成了{{1}之前的进程列表抓取,这很容易发生开始了。

其次,您对grep的使用很奇怪 - 因为它在进程中,它将等待任何子进程的子进程退出。由于没有,它将返回wait(&pid)(如果有,它将覆盖ECHILD孙子的退出状态。)

第三,您使用pidtcmdargs以及cmdargs2来决定哪个count调用仅在表单中有效execlp - 几乎任何其他组合都不起作用。几点:

  • 而不是cmd1 arg1 | cmd2 arg2来保存管道之后的参数,您需要记住在哪个位置看到管道(例如,而不是[i -3],当您找到管道时使用t=1保存后面的参数时{和t=i+1。)。
  • 你要查看函数调用的cmdargs2[i-t]版本,以便传入参数数组(记住在命令行中的所有参数之后添加一个NULL元素)。 / LI>