In the below program (which is not mine, but one which I have modified), the child process makes two writes to the pipe. When I run the program, I get the following output:
Received string: Hello, world!
This is the child process.
How is it that the read performed by the parent process captures both of these strings from the pipe buffer? What (if anything) prevents the parent process from assuming after it has read the first string (or the first char of the first string for that matter) that there is nothing else to read from the buffer, and exiting?
Program in question:
int main(void)
{
int fd[2], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char string2[] = "This is the child process.\n";
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
return 1;
}
if(childpid == 0)
{
/* Child process closes pipe's input file descriptor */
close(fd[0]);
/* Send "string" through the output side of pipe */
write(fd[1], string, (strlen(string)));
write(fd[1], string2, (strlen(string2)+1));
return 1;
}
else
{
/* Parent process closes pipe's output file descriptor */
close(fd[1]);
/* Read in a string from the pipe */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
return 0;
}
The rule is quite simple. For a blocking socket, the read will wait until there is some data to read, that could be 1 byte or 1MB. The kernel will then copy over as much data at the kernel has in its internal buffer, or the number of bytes requested, whichever is the smaller.
The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of existing data in the file.
Definition and Usage. The read() method returns the specified number of bytes from the file. Default is -1 which means the whole file.
The key here is the read()
buffer size 80
.
Usually read()
block the process which is calling it (is set in a sleeping status) until certain conditions doesn't happen, for example:
EOF
) or an error occurred^C
), this may be your case, the child process exit and the system send a broken pipe signal to the parent (the process wake and read()
get the whole buffer)Note that those conditions depends on the subsystem you are reading from, in your case a pipe
. Subsystem which may have different properties, like buffer size. An absurd example: if pipe buffer size on kernel side was less than or equal to your first write, the reading process would have wake up earlier returning a truncated buffer.
I love this question. It makes me remember old time ...
Meta-answer: It does only know, if the stream is closed
Answer: your process reads all it can/has to read, no end stops at '\n'
But I suppose, you want to write/read records.
Despite others I try to answer without distinguishing types of streams. I make a disclaimer here:
it all depends on OS and stream type - and the options opening on both (!) sides
Basic:
Lets say one process writes an other reads - easy enough.
No is not.
Imagine - always ;-) - they put there chars (bytes) into the stream as they want and can - slowly - fast - one by one or all they buffered.
and you read it - no - not you and not your program - in between - byte by byte or on block or how the layer in between likes.
So if you want a record, there a only three possibilities:
Answer again:
in your case the child puts all chars in the stream the parent read them and over - why should one of them make a break?
Solution:
Depending on the OS and language and libs, you sometimes can tell the OS to make an / accept an end char (like \n) - sometimes your write read functions do that for you
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With