2012-11-03 58 views
4

我是非常新的Linux等。我無法讓我的腳本工作。我只是猜測,程序在執行tr函數時被暫停。我的linux下c prog有什麼問題:「ls -al | tr a-z A-Z> file.txt」?

#include <fcntl.h> 
#include <stdio.h> 
#include <unistd.h> 

int main() 
{ 

int pdesc[2]; 
pipe(pdesc); 

int a = fork(); 

if (a == 0) // child 
    { 

    dup2(pdesc[1],1); // chaning std_out to pipes_out 
    execlp("ls", "ls", "-l", "-a", NULL); 

    } 
else  //parent 
    { 
    wait(); 
    int file1 = open("file.txt", O_WRONLY|O_CREAT|O_TRUNC,0777); 
    dup2(pdesc[0], 0); // chaning std_in to pipes_in 
    dup2(file1, 1); // chaning std_out to file's stream 
    execlp("tr", "tr", "a-z", "A-Z", NULL); 
    } 



return 0; 
} 
+1

是這樣的:「參數列表必須以'NULL'指針終止,而且,由於這些是可變參數函數,所以必須將該指針**轉換爲**(char *)NULL'。 ? –

+0

您的輸出文件不應該是可執行的;它是一個數據文件,而不是一個程序。我建議它不應該公開寫入,也可能不是可寫組,但這就是我的安全意識('umask'將最有可能修復它。 –

回答

6

經典錯誤,所以,好問題。

您需要關閉父級和子級中未使用的管道文件描述符。

從管道的過程中閱讀了(本身)的開放管道寫入結束,所以管道永遠不會完全封閉的,所以它永遠不會提供了一個EOF。

此外,wait(2)導致死鎖,程序不包括<sys/wait.h>,並調用wait(2)缺少必需的參數。因爲外殼將等待父母完成,但不是孩子,實際上,在這裏調用wait(2)會很好。但在目前的兩個流程設計中,你沒有地方可以放置它,因爲在父母的execlp(2)之後你無法控制。解決這個問題的一種方法是再次使用父叉(),並且讓原始PID不做任何事情,除了在循環中等待(2),直到所有子節點完成爲止。

這是一個工作版本,請注意輸出文件模式的變化。

#include <fcntl.h> 
#include <stdio.h> 
#include <unistd.h> 

int main() 
{ 
int pdesc[2]; 

    pipe(pdesc); 

    int a = fork(); 

    if (a == 0) { // child 
     dup2(pdesc[1],1); // chaining std_out to pipes_out 
     close(pdesc[1]); 
     close(pdesc[0]); 
     execlp("ls", "ls", "-l", "-a", NULL); 
    } else {  //parent 
     int file1 = open("file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644); 
     dup2(pdesc[0], 0); // chaning std_in to pipes_in 
     dup2(file1, 1); // chaning std_out to file's stream 
     close(pdesc[0]); 
     close(pdesc[1]); 
     close(file1); 
     execlp("tr", "tr", "a-z", "A-Z", NULL); 
    } 
    return 0; 
} 
+0

它沒有等待(),但我不知道爲什麼Isnt wait()(不帶參數)等待子進程死亡 – Patryk

+0

問題在於,wait需要在關閉操作之後但在execlp之前才能進行sort-of *工作。在那個位置,如果'ls'產生足夠的輸出來暫停自己,它會導致死鎖(內核將不會緩衝任意大量的傳輸管道內容)。「man 2 wait」找出準確的應該怎麼做你的電話。 – DigitalRoss