在shell中连接n个命令与管道?

我试图在C中实现一个shell。我可以使用简单的execvp()执行简单的命令,但是其中一个要求是管理像这样的命令:“ls -l | head | tail -4” ‘循环,只有一个’pipe()’语句重定向stdin和stdout。几天后,我有点迷失了。

N =简单命令数(示例中为3:ls,head,tail)
命令=具有命令的结构体列表,如下所示:

commands[0].argv[0]: ls
commands[0].argv[1]: -l
commands[1].argv[0]: head
commands[2].argv[0]: tail
commands[2].argv[1]: -4

所以,我做了for循环,并开始重定向stdin和stdout,以连接所有的命令与管道,但…我只是无知为什么它不起作用。

for (i=0; i < n; i++){

pipe(pipe);
if(fork()==0){  // CHILD

    close(pipe[0]);
    close(1);
    dup(pipe[1]);
    close(pipe[1]);

    execvp(commands[i].argv[0],&commands[i].argv[0]);
    perror("ERROR: ");
    exit(-1);

}else{      // FATHER

    close(pipe[1]);
    close(0);
    dup(pipe[0]);
    close(pipe[0]);

}
}

我想要创建的是一个“进程”的子进程:

[ls -l] —-pipe—-> [head] —-pipe—-> [tail -4]

所有这些进程都有一个根(这个进程运行我的shell),所以,第一个父亲也是一个shell进程的一个小孩,我有点疲惫已经有人可以帮助我吗?

我甚至不知道孩子是否应该是执行命令的人。

多谢你们 !!

没有什么复杂的,只要记住,最后一个命令应该输出到原始进程的文件描述符1,第一个应该从原始进程文件描述符0读取。你只是按顺序产生进程,沿着输入端以前的管道呼叫。

所以,这里有以下类型:

#include <unistd.h>

struct command
{
  const char **argv;
};

使用简单明确的语义来做一个帮助函数

int
spawn_proc (int in,int out,struct command *cmd)
{
  pid_t pid;

  if ((pid = fork ()) == 0)
    {
      if (in != 0)
        {
          dup2 (in,0);
          close (in);
        }

      if (out != 1)
        {
          dup2 (out,1);
          close (out);
        }

      return execvp (cmd->argv [0],(char * const *)cmd->argv);
    }

  return pid;
}

这是主要的例程:

int
fork_pipes (int n,struct command *cmd)
{
  int i;
  pid_t pid;
  int in,fd [2];

  /* The first process should get its input from the original file descriptor 0.  */
  in = 0;

  /* Note the loop bound,we spawn here all,but the last stage of the pipeline.  */
  for (i = 0; i < n - 1; ++i)
    {
      pipe (fd);

      /* f [1] is the write end of the pipe,we carry `in` from the prev iteration.  */
      spawn_proc (in,fd [1],cmd + i);

      /* No need for the write end of the pipe,the child will write here.  */
      close (fd [1]);

      /* Keep the read end of the pipe,the next child will read from there.  */
      in = fd [0];
    }

  /* Last stage of the pipeline - set stdin be the read end of the prevIoUs pipe
     and output to the original file descriptor 1. */  
  if (in != 0)
    dup2 (in,0);

  /* Execute the last stage with the current process. */
  return execvp (cmd [i].argv [0],(char * const *)cmd [i].argv);
}

还有一个小小的考验:

int
main ()
{
  const char *ls[] = { "ls","-l",0 };
  const char *awk[] = { "awk","{print $1}",0 };
  const char *sort[] = { "sort",0 };
  const char *uniq[] = { "uniq",0 };

  struct command cmd [] = { {ls},{awk},{sort},{uniq} };

  return fork_pipes (4,cmd);
}

出现工作:)

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...