两个孩子执行ls -la | grep使用管道

时间:2017-01-05 14:26:52

标签: c pipe fork exec ls

嘿,我有一个问题,了解此代码失败的地方。 它可能在执行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);
   }

所以我想有一个问题是写入和/或从管道读取。有谁知道我的问题? :/

1 个答案:

答案 0 :(得分:1)

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

此外,execvpe()的最后一个参数应该是指向以NULL结尾的char *数组的第一个元素的指针。虽然指向数组可能没有除终结符之外的元素,但我找不到允许参数本身为NULL的文档。如果您确实要为执行程序指定空白环境,那么execvpe()个调用都应采用以下一般形式:

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

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

此外,将程序参数打包到一个只使用 进行exec调用的数组中似乎有点愚蠢。 exec的varargs变体规避了任何需要(execl()等)。

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

因此,考虑到所有这些因素,并假设可以提供父流程环境的grepls个副本,这是我建议的一般形式为你的执行电话:

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