2014-03-12 70 views
0

嘗試回答練習時,我遇到了問題,這需要第一個進程逐行寫入管道,第二個進程從緩衝區讀取該管道只有20個字節。似乎有些信息在管道中「丟失」,並且輸入中缺少初始消息的隨機位。下面是有關該問題的代碼:將管道重複讀入小緩衝區的問題

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 

#define BUFF_SIZE 20 
#define LINE_SIZE 150 


int main(){ 

    pid_t idp1, idp2; 
    int pipefd[2]; 
    if (pipe(pipefd) == -1) return 3; //Pipe error 


    if ((idp1 = fork()) == 0){ 

     //SON 1 
     close(pipefd[0]); 
     FILE* input = fopen("input.txt", "r"); 
     char line[LINE_SIZE]; 

     //Get a line 
     while(fgets(line, LINE_SIZE, input)){ 


      //Sends the line 
      write(pipefd[1], line, LINE_SIZE); 
      sleep(1); 
     } 
     fclose(input); 
     close(pipefd[1]); 

    }else if(idp1 != -1){ 

     if ((idp2 = fork()) == 0){ 

      //SON 2 
      close(pipefd[1]); 
      char inMsg[BUFF_SIZE] = ""; 
      int received; 

      while(received = read(pipefd[0], inMsg, BUFF_SIZE)){ 
       inMsg[received] = '\0'; 
       printf("%.*s", received, inMsg); 
      } 

     }else if(idp2 != -1){ 

      //Father 
      close(pipefd[0]); 
      close(pipefd[1]); 
      //SleepOrWhatever(); 

     }else return 2; //Fork 2 error 

    }else return 1; //Fork 1 error 

    return 0; 

} 

現在,通過添加延遲(每行的進入管道的輸入之後休眠)時,它解決了上述問題。這是爲什麼 ?無論如何要避免這種情況?下面是結果與睡眠和無殼:

[010][input.txt] 
[049][[Fichier d'entrée du programme TD0 forkpipe.c].] 
[001][] 
[054][[003]Il contient des lignes [de longueurs variables].] 
[041][avec des lignes blanches (longuer [000])] 
[001][] 
[009][d'autres] 
[020][   commencant] 
[036][     par des blancs.] 
[010][et enfin,] 
[021][une dernière ligne.] 


[010][input.txt] 
hier d'entrée du programme TD0 forkpipe.c].] 
[001][] 
]Il contient des lignes [de longueurs variables].] 
[041][avec des lignes blanches (longuer [000])] 
[009][d'autres] 
    commencant] 
[036][     par des blancs.] 
nfin,] 
[021][une dernière ligne.] 

PS:我也試圖與從管道更大的緩衝區大小,一切輸出精確的讀取。如果它對管道的行爲有任何重要性,我也運行在Linux發行版上。

回答

1

考慮從文件讀取輸入時所發生的事情,即:

//Get a line 
while(fgets(line, LINE_SIZE, input)){ <<-- fgets reads a line _up_ to a LINE_SIZE bytes (and the result will be null terminated) 


    //Sends the line 
    write(pipefd[1], line, LINE_SIZE); <<-- Write LINE_SIZE bytes to the pipe 
} 

因此,考慮在你的文件中的幾行,你可以閱讀例如60個字節的fgets,然後你寫150個字節到管道(意思是90個字節的垃圾也到那裏)。

你結束了這個:

輸入:

first line 
second line 
third line 

管數據:

first line***second line*** third line *** 

***象徵寫入管道的垃圾數據。一旦第二個進程開始讀取,根據垃圾數據,它可以打印任何想要的內容。

+0

工作就像一個魅力,我會期待寫在字符串的結尾停止。你有什麼想法爲什麼它在睡眠中工作? –

+1

睡眠工作最有可能是垃圾是所有的空讓第二個進程有足夠的時間清空管道緩衝區(並且printf沒有打印所有NULL字節)。至於缺少一些字節的文本,考慮20字節邊界是否以NULL終止的垃圾字節開始,例如「'\ 0'mystsring」。然後printf會忽略這一點,並丟棄你的真實數據。 – Milan