加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-15 19:10:16 所属栏目:安全 来源:网络整理
导读:我试图在C中实现一个shell。我可以使用简单的execvp()执行简单的命令,但是其中一个要求是管理像这样的命令:“ls -l | head | tail -4” ‘循环,只有一个’pipe()’语句重定向stdin和stdout。几天后,我有点迷失了。 N =简单命令数(示例中为3:ls,head,t
我试图在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);
}

出现工作:)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读