我在尝试回答一个练习时遇到问题,这需要第一个进程逐行写入管道,第二个进程从一个只有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;
}
现在,通过添加延迟(每行输入管道后的睡眠),它解决了问题。这是为什么 ?无论如何要避免这种情况吗?这是shell中带睡眠但没有的结果:
[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发行版上运行。
答案 0 :(得分: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
}
因此,如果您的文件中有几行,您可以阅读,例如使用fgets创建60个字节,然后向管道写入150个字节(这意味着90个字节的垃圾也会出现在那里)。
你最终得到了这个:
INPUT:
first line
second line
third line
管道数据:
first line***second line*** third line ***
***
表示写入管道的垃圾数据。一旦第二个进程开始读取,根据垃圾数据,它可以打印任何想要的内容。