2012-08-07 20 views
2

這只是較大程序的一小部分,但是我試圖從execvp獲得輸出 我使用dup2正確設置了execvp,它指示它成管道。 當我使用read來讀取管道的全長時,我的問題就來了。我不知道每次輸入execvp有多大,因爲根據輸入的不同,它可能會有所不同。從execvp接收輸出時,從管道中讀取適量的數據

int fd[2]; 
    pipe(fd); 
    pid_t pid = fork(); 
    if (pid == 0) { 
     close(fd[0]); 
     dup2(fd[1], 1); 
     execvp(msg.v,(char *[]){msg.v,NULL}); 
    } else if (pid > 0) { 
     close(fd[1]); 
     read(fd[0],msg.v,....); 
    } 

我曾嘗試讀一些不同的大小,但它的要麼不夠或我結束了在我知道你可以使用POPEN結束,從標準輸入輸出一些其他的東西,但得到隨機的垃圾其所需的分配我們不會使用它們來消除其他方式來獲取輸出。

有點無用信息整個程序是服務器的一部分。我做了一個服務器和一個客戶端..啓動服務器給客戶端一個終端命令,它通過一個INET流將它發送到服務器,並將輸出發送回客戶端以顯示所有沒有stdio的輸出。

回答

1

您必須注意多少數據read返回到您的緩衝區。雖然read正在返回正數,但您有更多數據。程序完成後,它將關閉pipe的末尾,並且您的read將返回0

} else if (pid > 0) { 
    close(fd[1]); 
    ssize_t r = read(fd[0],buf,bufsz); 
    if (r > 0) do { 
     /* ... do something with r bytes in buf */ 
     r = read(fd[0],buf,bufsz); 
    } while (r > 0); 
    if (r < 0) { 
     perror("read"); 
     /*...*/ 
    } 
} 

如果你看到read給出一個「被中斷的系統調用」的錯誤,那麼你可能遇到了CAF提到EINTR情況。在這種情況下,您重新啓動您的read

 for (;;) { 
      r = read(fd[0],buf,bufsz); 
      if (r != -1 || errno != EINTR) break; 
     } 

我假設你是不是做非阻塞I/O,這樣你就不會遇到「資源暫時不可用」的消息。

+0

我沒有提到這一點,但我們可以使用stdio不preform IO,所以我能夠循環和使用sprintf拼湊我的消息,謝謝這有助於! – Mintybacon 2012-08-07 02:14:32

+0

@Mintybacon:你很受歡迎。問候 – jxh 2012-08-07 02:15:36

1

您隨時閱讀,直到read()回報0,這表明EOF(或-1,errno設置爲永久錯誤,這是以外的任何其他EAGAINEINTR)。

您不能忽略返回值read() - 它會告訴您返回了多少個字節。這就是爲什麼你在緩衝區結尾看到「垃圾」的原因 - 在這些情況下,read()沒有填滿整個緩衝區,並且你忽略了返回值,所以你不知道它實際返回了多少。