【问题标题】:Two Children to execute ls -la | grep using pipes两个孩子执行 ls -la | grep 使用管道
【发布时间】:2017-05-20 03:24:28
【问题描述】:

嘿,我在理解此代码失败的地方时遇到了问题。 它可能在执行 execvpe(grep) 的地方失败(控制台:“Grep 错误”)。

代码如下:

int main(int argc, char *argv[]){

   printf("filter.c\n");

   int fd[2];
   pid_t ls,grep;


   if(argc<3){
    printf("Bitte 2 Argumente angeben <Verzeichnis> <Suchmuster>");     
    exit(-1);
   }

   char verzeichnis[256];
   char suchmuster [256];
   char kind       [256];

   strcpy(verzeichnis,argv[1]);
   strcpy(suchmuster ,argv[2]);

   if(pipe(fd)<0){
       printf("Pipe fehlgeschlagen\n");
       return -1;
   }

   if((ls=fork())==-1){
    //fehler
    printf("Fork ls fehlgeschlagen\n");
    exit(-1);
   } else if(ls==0){
    //kind
    printf("\nChild1 laueft(ls)\n");
    if(dup2(fd[1],STDOUT_FILENO)==-1){//dupliziert fd[1]
        printf("Dup failed(ls)\n");
        return -1;
    }

       close(fd[0]);
       close(fd[1]);


       char *argu[]={"-la",verzeichnis,NULL};
       if(execvpe("bin/ls",argu,NULL)==-1){//EXECVE
           printf("ls error");
           return -1;
       }
       return -1    }

   if((grep=fork())==-1){
       //fehler
       printf("Forken von grep fehlgeschlagen\n");
       return -1;
   } else if(grep==0){
       //children2
       printf("Child 2 lauft (grep)\n");
       if(dup2(fd[0],STDIN_FILENO)==-1){
           printf("dup2 fd[0] fehlgeschlagen\n");
           return -1;
       }
       close(fd[0]);
       close(fd[1]);


       char *argu[]={"bin/grep",suchmuster,NULL};       
       if(execvpe("bin/grep",argu,NULL)==-1){
           printf("Grep error");
           return -1;
       }
       return -1;
   }
   close(fd[0]);
   close(fd[1]);

   while(wait(NULL)>0);//while()
   return 0;


   //   exit(0);
   }

所以我想有一个问题写入/读取管道。有人知道我的问题吗? :/

【问题讨论】:

  • 确定代码在哪里失败的关键信息是如何失败。您要解决的问题的具体性质是什么?
  • 它返回“Grep 错误”,所以它必须在那里..
  • 除非你从 / 目录运行你的程序,否则你应该添加正确的 grep 路径。试试"/bin/grep"
  • 请改进缩进。代码很难阅读。
  • @Gerhardh /bin/grep 没有解决我之前尝试过这个和其他事情的问题。

标签: c pipe fork exec ls


【解决方案1】:

如果给定的可执行文件路径包含/ 字符,则不执行搜索。在这种情况下,如果需要,将相对于调用时进程的当前工作目录解析给定的路径。这很少是人们想要的,你的情况看起来也不例外。此外,如果您确实要指定二进制文件的路径而不是简单的名称,那么您从 exec 的路径搜索变体中没有任何优势。

此外,execvpe() 的最后一个参数应该是指向 char * 的以 NULL 结尾的数组的第一个元素的指针。尽管指向的数组可能除了终止符之外没有其他元素,但我发现没有文档表明参数本身允许为NULL。如果您确实想为执行的程序指定空环境,那么,execvpe() 调用都应采用以下通用形式:

char *argu[] = { "grep", suchmuster, NULL };      
char *env[] = { NULL };
if (execvpe("/bin/grep", argu, env) == -1) {

此外,使用空环境执行外部进程是值得怀疑的,但不一定是错误的。为此,我没有看到太多优势,您可以通过使用其中一个 exec 函数来省去一些麻烦,该函数只是将调用进程的环境副本提供给 exec'ed 映像。例如,execvp() 将是最接近具有该特征的execvpe() 的那个。

此外,将程序参数打包到一个数组中,only 用于 exec 调用似乎有点愚蠢。 exec 的 varargs 变体避免了这样做的任何需要(execl() 等)。

exec 函数仅在出错时返回。您可以测试返回值,但如果这些函数完全返回,那么它们的返回值始终为 -1。

因此,考虑到所有这些,并假设可以提供父进程环境的 grepls 副本,这是我建议您的 exec 调用的一般形式:

       execl("/bin/grep", "grep", suchmuster, NULL);
       // an error occurred
       perror("execing grep");
       _Exit(1);

【讨论】:

  • 如果我正在执行 execl("bin/ls","-la",Verzeichnis,NULL);错误();然后它退出那里(没有这样的文件或目录)。我试过“/home”“home”“。”和 ”..”。我插入了错误的参数吗?当前工作目录下没有子文件夹
  • @Felix,你给出了一个包含/ 但不是以一个开头的路径。正如我已经解释过的,它将相对于当前工作目录进行解析,而不在路径中查找。例如,如果工作目录是 /home/felix,那么 exec 将查找 /home/felix/bin/ls,并且 only 查找该目录。遵循我提出的模型。
猜你喜欢
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-10
相关资源
最近更新 更多