【问题标题】:Pipes & exec & C管道 & 执行 & C
【发布时间】:2015-06-04 05:14:39
【问题描述】:

您好,我有以下问题,我必须创建一个程序来执行这些 Linux 命令ls –la | sort | wc –l,但在我的代码中我只能读取其中两个命令,sameone 可以帮助我吗??

int main(){
  pid_t pids[3];
   int dados[2],dados2[2],i;

    if(pipe(dados) == -1 && pipe(dados2) == -1){
       perror("pipe failed");
       exit(1);
     }

  for(i=0;i<3;i++){
      pids[i] = fork();
      if(pids[i] == 0){ 
          if(i==0){
            close(dados[0]);
            dup2(dados[1],1);
            close(dados[1]);

            execlp("ls","ls","-la",NULL);
            perror("exec failed");
            exit(-1);
        }
        if(i==1){
            close(dados[1]);
            dup2(dados[0],0);
            close(dados[0]);


            close(dados2[0]);
            dup2(dados2[1],1);
            close(dados2[1]);

            execlp("sort","sort",NULL);
            perror("exec failed");
            exit(-1);
         }else{
            close(dados2[1]);
            dup2(dados2[0],0);
            close(dados2[0]);
            printf("aaaaaaaaaaaaaaaaaa");
            execlp("wc","wc","-l",NULL);
            perror("exec failed");
            exit(-1);
         }
     }
 }

 /* Pai tem de fechar a sua copia da extremidade de escrita 
  para a leitura do sort desbloquear */
 close(dados[1]);
 close(dados2[0]);
 for(i=0;i<3;i++){
     wait(NULL);
 }

return 0;

}

我不明白这有什么遗漏

【问题讨论】:

    标签: c linux unix pipe exec


    【解决方案1】:

    让我眼前一亮的是

    -if(pipe(dados) == -1 && pipe(dados2) == -1){
    +if(pipe(dados) == -1 || pipe(dados2) == -1){
    
       perror("pipe failed");
       exit(1);
    }
    

    父 pid 只需要读取最后一个命令的输出,因此父 pid 需要关闭所有其他管道端。子进程需要关闭 stdin/stdout 和 dup2() 管道描述符以将它们绑定到 stdin/stdout 然后 exec()。对于管道,关闭流程中不需要的管道端非常重要。见http://linux.die.net/man/2/pipe

    目前我没有 linux box,所以我无法编写和测试 linux 代码。

    我给你的总结是: - 父从最后一个管道读取(链中最后一个进程的标准输出) - 所有其他孩子需要关闭()他们的标准输入/标准输出,dup2()正确的管道,关闭所有不需要的管道(记住也要关闭dup2()源,因为它是一个fd)然后执行。

    这是我如何创建管道并重新绑定 fds 的示例。

    // unset FD_CLOEXEC
    set_close_on_exec(to_child,false);
    set_close_on_exec(from_child, false);
    
    // close and rebind the stdin/stdout/stderr
    // dup the fd and recreate stdin/stdout with fd as the target
    if (dup2(to_child, STDIN_FILENO) != 0 || dup2(from_child, STDOUT_FILENO) != 1) {
        shared::perror("error duplicating socket for stdin/stdout");
        exit(EXIT_FAILURE);
    }
    
    // close these FDs
    close(to_child);
    close(from_child);
    
    // now we can exec the new sub process and talk to it through
    // stdin/stdout/stderr
    execlp(exe.c_str(), exe.c_str(), argv.c_str(), (char*)0);
    
    // this should never be reached
    shared::perror("error: executing the binary: " + exe);
    exit(EXIT_FAILURE);
    

    请记住,在 pipe(int fds[2]) 处,索引 1 是管道的写入端,而索引 0 是管道的读取端。所以你需要

    问候 乔治

    编辑:我向您推荐《Linux 编程接口:Linux 和 UNIX 系统编程手册》一书 ISBN-13:978-1593272203

    【讨论】: