Reputation: 83
I am trying to send ten messages from a child process to the parent. But the output of the program shows that parent process read the first and sixth messages only. I tried to change the sleep() position in the code, also I tried to use while() to read instead of for() but the problem remains the same. Here is the code:
int main(int argc, char *argv[]){
char ch, message_from_A[100], message_from_B[100], msg_to_log[100], msg_to_B[100];
int i, x, fd_log[2], fd_A_B[2], fd_B_C[2], fd_B_D[2];
pipe(fd_log);
//fork process A
if (fork()==0) { //child
printf("Inside process A\n");
for (i=0; i < 10; i++) {
//creat new msg
x = (rand() % 2);
if (x == 1)
ch='C';
else
ch='D';
//write msg to log pipe
sprintf(msg_to_log, "A sent to B: %c %d\n", ch, i);
printf("wirtten to log pipe--> %s\n", msg_to_log);
close(fd_log[READ]);
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
}//end for()
close(fd_log[WRITE]); //this line won't affect output
_exit(1);
} else { //parent
printf("Inside process log\n");
close(fd_log[WRITE]);
while ( read(fd_log[READ], message_from_A, 100) > 0 ) {
sleep(1);
printf("\nmsg from A: %s", message_from_A);
}
close(fd_log[READ]); //this line won't affect output
}}
The output of this program shows the parent reads only the first and sixth messages! This is the output:
Inside process log
Inside process A
wirtten to log pipe--> A sent to B: C 0
wirtten to log pipe--> A sent to B: C 1
wirtten to log pipe--> A sent to B: C 2
wirtten to log pipe--> A sent to B: D 3
wirtten to log pipe--> A sent to B: D 4
wirtten to log pipe--> A sent to B: D 5
wirtten to log pipe--> A sent to B: D 6
wirtten to log pipe--> A sent to B: D 7
wirtten to log pipe--> A sent to B: C 8
wirtten to log pipe--> A sent to B: C 9
msg from A: A sent to B: C 0
msg from A: B: D 5
I appreciate any ideas or suggestions.
Upvotes: 1
Views: 137
Reputation: 5298
The culprit here seems to be this line:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log)+1);
That should be:
write(fd_log[WRITE], msg_to_log, strlen(msg_to_log));
Else you are sending an extra character (which will be '\0'
, msg_to_log
being global).. Hence eventhough the read()
succeeds, it won't print the whole sequence of characters(but only until the '\0'
). Also memset
msg_to_log
before filling it in each time (to make sure none of the old characters are hanging in there). Also memset
message_from_A
after each print (for the same reason).
Also, move close(fd_log[READ]);
before the for loop.
Upvotes: 1
Reputation: 340336
In the child you are writing several blocks of data that look something like:
A sent to B: C x
each followed by a null character (the 'x' above is replaced by a number indicating the line of data written to the pipe). However the process that is reading the pipe will read whatever has been put into the pipe up to the limit specified in the read()
function call - it doesn't stop at the null character. So the first read()
might grab the first 100 characters from the following that might be in the pipe:
A sent to B: C 0\0A sent to B: C 1\0A sent to B: C 2\0A sent to B: C 3\0A sent to B: C 4\0A sent to B: C 5\0
However, when the parent displays what is read from the pipe, it prints it as a null terminated string, so only the first part of the buffer is displayed.
Then the next read picks up the fragment that was left in the pipe (and anything after that fragment), and again displays only until the null character.
To fix the problem use the return code from read()
to figure out what has been returned, and deal appropriately with the null characters.
Upvotes: 3