2011-11-27 54 views
3

我的程序正在控制Linux上的外部應用程序,通過管道將輸入命令傳遞到外部應用程序stdin,並通過外部應用程序stdout的管道讀取輸出結果。有沒有辦法將Linux管道設置爲非緩衝或線路緩衝?

問題是寫入管道是按塊緩存,而不是按行存放,因此延遲發生在我的應用程序接收到外部應用程序輸出的數據之前。無法更改外部應用程序以添加顯式fflush()調用。

當我的外部應用程序設置爲/斌/貓-n(它回顯輸入,添加了行號),它工作正常,現在看來,在每行後刷新。強制外部應用程序刷新的唯一方法是將退出命令給它;當它收到命令時,它會刷新,所有答案出現在stdout上,就在退出之前。

我很確定,Unix管道是適合那種進程間通信(僞服務器客戶端)的解決方案,但也許我錯了。

(我剛剛複製了一個類似的問題,一些文字:Force another program's standard output to be unbuffered using Python

+0

這是另一個優秀的Linux緩衝討論: http://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe – AAAfarmclub

回答

5

請勿使用管道。改用pty。如果您需要,Pty(僞ttys)具有線緩衝的優點,它爲您的數據流提供了簡單的幀。

0

爲什麼叫fflush適當(寫入側)不爲你工作?

可以使用poll(或其他系統調用一樣ppollpselectselect)檢查讀出側輸入的可用性。

如果外部應用程序使用,而不<stdio.h>適當調用fflush(可能由setbuf使它發生在換行符....),數據將保持其FILE*緩衝器內,甚至沒有被髮送(具有write系統調用)的管!

應用程序可以檢測其輸出是否是具有例如終端的終端。 isatty。但它應該確保沖洗發生...

正如邁克爾狄龍建議,使用pty-s可能是最好的。但很難(我忘記了血淋淋的細節)。

+0

答案很簡單:這不是我的計劃。 (困難的答案:我們試圖將Delphi的東西移植到Linux上;外部程序是一個Delphi運行的命令行util,我不確定Delphi的flush()是幹什麼的,它是否會工作。試試吧,但即使它的工作原理,這個問題值得解決的問題。) – ern0

+0

但如果應用程序沒有沖洗,那麼它是越野車來的是無法使用的地步... –

+0

應用在外殼的偉大工程。嗯,我現在有一個想法。 – ern0

1

默認情況下,標準輸入和標準輸出會被完全緩衝,除非它們連接到交互式設備,在這些交互設備中,它們是線路緩衝的[1]。管道是非交互式設備。 PTYs 交互式設備。 「完全緩衝」是指「使用一定大小的內存塊」。

我確定你想要行緩衝。因此,使用主/從PTY而不是管道應使受控應用程序自動進入正確的緩衝模式。

[1]詳情請參閱「stdin(3)」和「setbuf(3)」。

2

使用PTY可能是對手頭問題的矯枉過正(雖然它工作)。

如果「目標應用程序」(Delphi命令行實用程序)是動態鏈接的,則可能更簡單的解決方案是在應用程序中插入(通過LD_PRELOAD)一個小型庫。該庫只需要執行isatty,並回答true(返回1)無論輸出是否將管道或終端。您可能希望對所有文件描述符執行此操作,或者僅針對STDOUT_FILENO執行此操作。

大多數UNIX實現將調用isatty來決定是否做全緩衝或行緩衝對於一個給定的文件描述符。

嗯,glibc不。它要求__fxstat,然後只有當狀態指示fd是要一個字符設備調用isatty。所以你需要介入__fxstatisatty。更多關於圖書館介入here

+0

下面是使用PTY http://rachid.koucha.free.fr/tech_corner/pty_pdip.html#Inter-process_communication_through_a一個很好的例子 – ern0