Issue
Hi I have a C programme that is basacally suppose to simulate the pipe function in linux and write the amount of bytes that are read in a .txt file so
./a.out cat test : grep -v le : wc -l
The problem that I'm trying to figure out is
Why is the same amount of bytes written in the file since I know each process returns a different amount ?
This piece of code is executed in the parent and is trying to count the amount of bytes of each output with a read syscall and writes the output in a write syscall in the next process so that the next process can use the output as his input.
So let's say I have these pipes a | b | c
This code will read the output of a
and write it in b
so that b
can use it as it's input and so on.
for (int i = 1; i < processes-1; i++) {
close(apipe[i][1]);
char str[4096];
int count=0;
int nbChar=0;
while(1){
count=read(apipe[i][0],str,sizeof(str));
nbChar+=count;
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
}else if(count==0)break;
}
char *leInput=(char*)malloc(nbChar*sizeof(char));
strncpy(leInput,str,nbChar);
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
write(apipe[i+1][1], leInput, nbChar);
}
Solution
Each time through the while(1)
loop you're read into the beginning of str
, not where you left off in the previous iteration. So you're overwriting the previous read with the next read.
You should copy incrementally to leInput
each time through the loop. You can then use realloc()
to grow it to accomodate the new input, and you can use leInput + nbChar
to copy after the place where you finished the previous time.
for (int i = 1; i < processes-1; i++) {
close(apipe[i][1]);
int nbChar=0;
char *leInput = NULL;
while(1){
int count=0;
char str[4096];
count=read(apipe[i][0],str,sizeof(str));
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
} else if(count==0) {
break;
}
leInput = realloc((nbChar + count)*sizeof(char));
memcpy(leInput + nbChar, str, count);
nbChar += count;
}
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
write(apipe[i+1][1], leInput, nbChar);
}
Alternatively you could just write to the next pipe in the inner loop, without collectiong everything into leInput
:
for (int i = 1; i < processes-1; i++) {
int nbChar = 0;
close(apipe[i][1]);
while(1){
int count=0;
char str[4096];
count=read(apipe[i][0],str,sizeof(str));
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
} else if(count==0) {
break;
}
write(apipe[i+1][1], str, count);
nbChar += count;
}
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
close(apipe[i+1][1])
}
Answered By - Barmar