2017-01-05 29 views
1

嘿,我有一个问题,了解这个代码失败的地方。 它可能会失败执行execvpe(grep)(控制台:“Grep Error”)。两个孩子执行ls -la | 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); 
    } 

,所以我想有一个问题写作,或从管道读取到/。有谁知道我的问题? :/

+0

在确定你的代码失败的地方,一个重要的信息就是*如何失败。你试图解决的问题的性质究竟是什么? –

+0

它返回“Grep错误”,所以它必须在那里.. – Felix

+1

除非你从/目录运行你的程序,你应该添加正确的路径到grep。尝试'“/ bin/grep”' – Gerhardh

回答

1

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

此外,execvpe()的最后一个参数应该是指向NULL结尾数组char *的第一个元素的指针。虽然指向数组可能没有除终止符以外的其他元素,但我发现没有文档说明参数本身允许为NULL。如果你确实想指定exec'ed方案空的环境,那么,无论是execvpe()调用应该采取这种一般形式为:

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

此外,空环境execing外部过程是令人怀疑的,虽然不一定是错的。为此目的,我没有看到太多的优势,并且可以通过使用一个exec函数来为执行的映像提供一个调用进程环境的副本,从而为您节省一些麻烦。例如,execvp()将是最接近具有该特征的execvpe()的那个。

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

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

考虑所有的考虑,因此,并假定这将是确定给父进程的环境grepls副本,这是一般形式,我建议你exec调用:

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

如果正在执行 execl(“bin/ls”,“ - la”,Verzeichnis,NULL); perror(); 然后它退出那里(没有这样的文件或目录)。我试过“/ home”“home”“。”和“..”。我要插入一个错误的论点?在当前工作目录 – Felix

+0

@Felix中没有子文件夹,您给出了一个包含'/'的路径,但不是以一个开头。正如我已经解释的那样,它将相对于当前工作目录进行解析,而不在路径中查找。例如,如果工作目录是'/ home/felix',那么exec将查找'/ home/felix/bin/ls',* only *。按照我介绍的模型。 –

+0

非常感谢现在工作:) – Felix