2013-07-25 91 views
0

我試圖改寫wc -l顯示部分結果重複,因爲它接收輸入(例如讀取,Linux的緩衝距離STDIO

我現在的版本是一個簡單的

while(!feof(in) && 
      //(readc=fread(buf, 1,BUFSIZE,in))) { 
      (readc=read(0,buf, BUFSIZE))) { 
      for(i=0;i<readc;i++) { 
        lines += (buf[i] == '\n'); 
      } 
    } 

問題是我的stdin仍然是塊緩衝的,這個練習的整個目的是讓輸出不必等待每個4KB的塊填充,我想線緩衝就沒問題了,

示例應用:find | partial_wc

awk 'NR%1000==0 {printf "%d\r",NR} END {print NR}'有一個類似的輸出,除了我想選擇輸出基於時間(例如每1秒),而不是行。另外,這是一個有趣的學習問題。

我嘗試了why grep is fast中給出的建議,但無法弄清楚要使用哪一組系統調用。

+0

試試fflush()是否工作? –

+0

fflush顯示爲「對於輸入流,fflush()會丟棄從底層文件中獲取但尚未被應用程序使用的任何緩衝數據。」這聽起來不像它會做我想要的。 – zebediah49

+0

注意'while(!feof(x))'幾乎保證是錯誤的。 – caf

回答

2

當然,嘗試POSIX終端控制API:

#include <termios.h> 

struct termios ctrl; 
tcgetattr(STDIN_FILENO, &ctrl); 
ctrl.c_lflag &= ~ICANON; // turning off canonical mode makes input unbuffered 
tcsetattr(STDIN_FILENO, TCSANOW, &ctrl); 
+0

未做出所需的更改。我認爲這是因爲這改變了終端控制,而我的輸入來自以前的過程?我的規範測試是比較'find | my_wc'對'unbuffer find | my_wc' - 第一次返回4096字節,而第二次返回最多次數<4096。 – zebediah49

+0

@ zebediah49對不起,我不明白「上一個過程」是什麼意思。是的,這改變了終端控制,但不是你想要的嗎?如果不在終端中,你還會關閉緩衝嗎? – 2013-07-25 04:23:56

+0

我指的是'previous_process | this_process'。我認爲終端變化影響了'終端內'(如基於鍵盤的輸入)。當stdin連接到我的鍵盤時,您的響應會執行規定的目標,但stdin連接到'find'時不會發生。 – zebediah49

2

問題是不是你標準輸入被塊緩衝,問題是該方法生成的數據的標準輸出是被塊緩衝。如果您要控制數據管道的整個流程鏈,則可以使用unbuffer來解決該問題,但在一般情況下,程序無法更改管道中上一個程序的輸出流的緩衝區。

+0

那麼這似乎是那個規範的答案。我認爲應該有一種方法,因爲我的測試案例,find | unbuffer -p cat | my_wc'具有所需的行爲('find | my_wc'沒有)。 – zebediah49

+0

不可否認,你的stdin也可能被塊緩衝,但這不是問題的原因。順便提一句,這裏混合了兩種不同類型的I/O:'feof()'函數與'fread()'(C庫緩衝I/O)一起使用,而不是'read()'(POSIX I/O)。 –