2015-01-07 41 views
0

我正在創建一個C程序,並且使用它我在進程間通信的獨立分叉進程之間設置了一個管道。如何對管道中的數據調用UNIX排序命令

第一個過程將我需要的數據寫入管道。 但是,在從管道讀取第二個進程時,我試圖執行該進程成爲UNIX排序命令。我想以某種方式調用管道中的數據進行排序。

如何在管道上調用排序?在命令行中,我可以通過提供文件名來排序,作爲命令行參數排序。 「sort -r MyFileToSort」。我知道管道本質上被認爲是文件,但是它們只是通過它們的文件描述符來描述,並且據我所知,sort不知道如何處理fd。

感謝所有幫助/反饋

+0

你已經試過了什麼? –

+0

這可能有所幫助:http://en.wikipedia.org/wiki/Named_pipe –

+0

@martinclayton,爲什麼在這裏需要命名管道?根據需要,可以簡單地將'mkpipe()'返回的FD附加到stdin或stdout。 –

回答

0
int p[2]; 
if (pipe(p) != 0) ...report error and do not continue... 
pid_t pid = fork(); 
if (pid < 0) ...report error, close pipe descriptors, and do not continue... 
if (pid == 0) 
{ 
    /* Child - becomes sort */ 
    dup2(p[0], 0); 
    close(p[0]); 
    close(p[1]); 
    int fd = open("output-file", O_CREAT | O_EXCL | O_WRONLY, 0644); 
    if (fd < 0) ...report error and exit... 
    dup2(fd, 1); 
    close(fd); 
    execlp("sort", "sort", (char *)0); 
    ...report error and exit... 
} 
else 
{ 
    /* Parent - writes data to sort */ 
    close(fd[0]); 
    ...write data to fd[1]... 
    close(fd[1]); 
    int status; 
    int corpse; 
    while ((corpse = wait(&status)) > 0 && corpse != pid) 
     ...consider reporting which child died... 
    ...consider reporting sort status... 
    ...continue with the rest of the program... 
} 

你可以決定是否上報相關dup2()失敗,或close()失敗的錯誤。除了報告問題和退出外,在任何情況下都無能爲力。除非有人通過不提供標準輸入,標準輸出和標準錯誤(或程序中其他地方關閉了任何標準通道)而使您的程序受到殘酷和異常的懲罰,否則管道和文件描述符不能標準的I/O描述符,所以關閉是安全的。如果你不知道你的用戶是如何生病的是,你可以保護關閉:

if (p[0] > FILENO_STDERR) 
    close(p[0]); 

這通常是不必要的偏執(但它可以與缺少標準I/O有趣的嘗試計劃)。

+0

謝謝你的代碼示例。我認爲這種排序必須明確地通過一個文件名,但我看到重定向標準輸入到管道,只是調用排序工程 – pleaver

+0

許多,但絕非所有的Unix程序作爲'過濾器'工作,並閱讀標準輸入,如果沒有給出文件名並寫入標準輸出。你可以使用:'execlp(「sort」,「sort」,「-o」,「output-file」,(char *)0);'而不是在代碼中進行I/O重定向。這會導致'sort'寫入'output-file'。一般來說,它允許'sort'寫入其中一個輸入文件;如果您採用這種改變,您只是將該選項用作副作用。如果你可能有排序選項,你應該考慮'execvp()'或'execv()'而不是'execlp()';您可以通過這種方式獲得可變長度參數列表。 –

0

你並不需要通過任何sort參數在這種情況下,在所有指定的輸入源或輸出匯。相反,在執行exec之前,應該將管道的文件描述符附加到它的標準輸入(如果從管道接收數據,則爲FD 0)或標準輸出(FD 1,如果將數據寫入管道)。

請參閱dup2()調用,該調用允許您設置複製FD的目的地,爲此目的。正如@JonathanLeffler指出的那樣,在執行調用之前,您需要確保關閉原始的FD(在將它們複製到所需的數字之後)。


既然你已經闡明,在註釋中,你的目標是要寫入一個文件,你會重視FD 1到目標文件調用exec前,用FD 0附着在管道的輸出側包含輸入。

+1

的答案,並在執行exec *()調用之前關閉未使用的文件描述符 - 在這種情況下,都是來自'pipe()'的文件描述符。 –

+0

謝謝,我重定向到管道的讀者的標準輸入,現在調用排序沒有指定的文件工作正常。我仍然有一個小問題,但這個問題的上下文已被回答 – pleaver