Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 定制linux shell中的管道_C_Linux_Pipe - Fatal编程技术网

C 定制linux shell中的管道

C 定制linux shell中的管道,c,linux,pipe,C,Linux,Pipe,尝试用一些基本函数实现我自己的linux shell,当然,在实现管道时会出现一个问题。更具体地说,管道在很大程度上起作用,尽管它似乎放弃了最后一个论点。例如,如果我要运行命令 ps ax | grep ps grep命令后的ps被放入我的shell中。因此,不要像使用典型的Linux shell那样输出它 339 ? S 0:00 upstart-udev-bridge --daemon 497 ? Ss 0:00 /usr/sbin/cupsd

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

ps ax | grep ps
grep命令后的ps被放入我的shell中。因此,不要像使用典型的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桥--守护进程
497 ?        Ss 0:00/usr/sbin/cupsd-F
503 ?        S<0:00[kps已用]
720 ?        S 0:00 upstart套接字桥--守护进程
5541分/0 R+0:00 ps ax
5542分/0s+0:00grep--color=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
339?S 0:00 upstart udev桥--守护进程
497 ?        Ss 0:00/usr/sbin/cupsd-F
503 ?        S<0:00[kps已用]
720 ?        S 0:00 upstart套接字桥--守护进程
5557分/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);
  }

  }

}
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;
整数计数=0;
对于(i=0;i0)
{
等待(&pid);
关闭(fd[1]);
关闭(0);
dup2(fd[0],0);
execlp(cmdargs2[0],cmdargs2[0],cmdargs2[1],NULL);
}
如果(pid==0)
{
关闭(fd[0]);
关闭(1);
dup2(fd[1],1);
execlp(cmdargs[0],cmdargs[0],cmdargs[1],NULL);
}
}
如果(计数=1)
{
管道(fd);
pid=fork();
如果(pid==-1)
{ 
佩罗尔(“无法叉叉”);
出口(1);
}
如果(pid>0)
{
等待(&pid);
关闭(fd[1]);
关闭(0);
dup2(fd[0],0);
execlp(cmdargs2[0],cmdargs2[1],NULL);
}
如果(pid==0)
{
关闭(fd[0]);
关闭(1);
dup2(fd[1],1);
execlp(cmdargs[0],cmdargs[1],NULL);
}
}
}
我已经检查了管道后面的所有变量是否仍然在第二组参数中,并且它们是唯一的问题不是主参数,而是在我执行实际管道的某个地方,它没有读到最后


首先,除非我遗漏了什么,否则您的两个示例输出看起来都正常工作:它们都只列出了带有“ps”的行。(如果它真的在运行
ps ax | grep
,那么
grep
会抱怨使用情况)。我在输出中看到的唯一区别是第二个没有列出
grep
进程本身,但是如果
ps
grep
启动之前抓取完进程列表,这很容易发生

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

第三,您可以使用
t
cmdargs
cmdargs2
以及
count
来决定只进行
execlp
调用的
cmd1 arg1 | cmd2 arg2
形式的调用——几乎任何其他组合都不起作用。有两点:

  • 您需要记住看到管道的位置,而不是
    [i-3]
    来保存管道后的参数(例如,在找到管道时使用
    t=i+1
    ,在保存管道后的参数时使用
    cmdargs2[i-t]
  • 您需要查看函数调用的
    execvp()
    版本,以便传入参数数组(记住在命令行的所有参数之后添加NULL元素)