2011-09-29 81 views
1

看看這個代碼:哪些錯誤與此打印順序

#include<stdio.h> 
#include <unistd.h> 
    int main() 
    { 
      int pipefd[2],n; 
      char buf[100]; 
      if(pipe(pipefd)<0) 
        printf("Pipe error"); 
      printf("\nRead fd:%d write fd:%d\n",pipefd[0],pipefd[1]); 
      if(write(pipefd[1],"Hello Dude!\n",12)!=12) 
        printf("Write error"); 
      if((n=read(pipefd[0],buf,sizeof(buf)))<=0) 
        printf("Read error"); 
      write(1,buf,n); 
      return 0; 
    } 

我期待中的printf要打印閱讀fd和之前從管道中讀取你好哥們寫的FD。但事實並非如此......見here。當我在我們學校的計算機實驗室嘗試同樣的程序我的產量

Read fd:3 write fd:4 
Hello Dude! 

也是我們幾個朋友指出,改變printf語句包含更多的\n字符數變化的輸出順序...例如。 printf("\nRead fd:%d\n write fd:%d\n",pipefd[0],pipefd[1]);表示讀取fd被打印,然後消息Hello Dude!然後寫入fd被打印。這是什麼行爲? 注意:出實驗室使用我們運行終端的Linux服務器,但我不記得編譯器版本。

回答

5

這是因爲printf到標準輸出緩衝,但write到標準輸出文件描述符是沒有的。

這意味着行爲可以根據你有什麼樣的緩衝來改變。在C中,標準輸出爲如果可以確定連接到交互式設備,則緩衝。否則它完全緩衝(見here爲什麼這是如此)。

行緩衝意味着它會在看到換行符時刷新到文件描述符。完全緩衝意味着它只會在緩衝區填滿時(例如,4K值的數據)或流關閉時(或者當您使用fflush時)刷新。

當您以交互方式運行它時,沖洗發生在write之前,因爲printf遇到\n並自動刷新。 (例如,通過將輸出重定向到文件或在線編譯器/執行程序,它可能會做同樣的事情來捕獲數據以供演示),則在之後沖洗發生write(因爲printf每行後都不沖洗)。

其實,你並不需要在那裏所有的管道東西看到這個動作,按照以下程序:

#include <stdio.h> 
    #include <unistd.h> 
    int main (void) { 
     printf ("Hello\n"); 
     write (1, "Goodbye\n", 8); 
     return 0; 
    } 

當我執行myprog ; echo === ; myprog >myprog.out ; cat myprog.out,我得到:

Hello 
Goodbye 
=== 
Goodbye 
Hello 

,你可以看到不同類型的緩衝所產生的差異。

如果你想行緩衝無論重定向,你可以嘗試:

setvbuf (stdin, NULL, _IOLBF, BUFSIZ); 

早在你的程序 - 它的實現定義的實現是否支持此所以它可能沒有任何效果,但我從來沒見過許多不起作用的地方。

4

您不應該在單個文件描述符上混合調用writeprintf。將write更改爲fwrite

使用FILE的功能被緩衝。使用文件描述符的函數不是。這就是爲什麼你可能會混合訂單。

您也可以嘗試在write之前致電fflush

1

發生了什麼是printf以緩衝方式寫入標準輸出 - 字符串在輸出之前保存在緩衝區中 - 而寫入標準輸出後的「寫入」未緩衝。這可能會導致'write'的輸出先出現,如果printf的緩衝區稍後才刷新。

您可以使用fflush()顯式刷新 - 但更好的辦法不是將緩衝和非緩衝寫入混合到同一個輸出。在終端上鍵入man printf,man fflush,man fwrite等,以瞭解更多關於這些命令的具體含義。

2

當你一次寫入同一個文件或管道,或者通過兩種方式寫入(直接IO和輸出流)時,你可以得到這種行爲。原因是輸出流被緩衝。

With fflush()您可以控制該行爲。

+2

嗨glglgl,我被管道分散注意力,忽略那一個:) – ypnos

+0

我的寫作'write(1,buf,n)'的意圖是打印到控制檯 – sasidhar

+0

thx澄清 - 我現在可以刪除我的評論:-) – glglgl