Sorry for the basic question, but I can't find a straight answer that I can understand on the documentation or with generative AI.
When I do a write
call over a pipe between a parent and child process, will write
only return something != -1 if the data is read by a read
system call?
For instance, take the following code below:
int main(int argc, char* argv[]) {
int workers = 4;
int pfd[2];
int pipe_result = pipe(pfd);
if(pipe_result != 0) {
fail("Can't create pipe");
}
// Parent doesn't need write channel
close(pfd[1]);
for(int i = 0; i < workers; i++) {
pid_t pid = fork();
// Child
if(pid == 0) {
// Child doesn't need read channel
close(pfd[0]);
int count = 101;
// Write count to pipe
int len_sent = write(pfd[1], &count, sizeof(count));
printf("\nChild id: %d Sent %d bytes, count: %d", getpid(), len_sent, count);
// Exit so that the child processes don't loop
close(pfd[1]);
exit(0);
}
else {
int par_count;
// Read
int len = read(pfd[0], &par_count, sizeof(par_count));
printf("\nlen: %d par_count: %d", len, par_count);
}
}
// Close read buffer in parent
close(pfd[0]);
return 0;
}
That code will generally output indicating that 0 or 1 write and read calls were successful. If I move the reads to be after all write calls are done (code below), then everything reports fine.
int main(int argc, char* argv[]) {
int workers = 4;
int pfd[2];
int pipe_result = pipe(pfd);
if(pipe_result != 0) {
fail("Can't create pipe");
}
for(int i = 0; i < workers; i++) {
pid_t pid = fork();
// Child
if(pid == 0) {
// Child doesn't need read channel
close(pfd[0]);
int count = 101;
// Write count to pipe
int len_sent = write(pfd[1], &count, sizeof(count));
printf("\nChild id: %d Sent %d bytes, count: %d", getpid(), len_sent, count);
// Exit so that the child processes don't loop
close(pfd[1]);
exit(0);
}
}
// Parent doesn't need write channel
close(pfd[1]);
// Parent
for(int i = 0; i < workers; i++) {
int par_count;
// Read
int len = read(pfd[0], &par_count, sizeof(par_count));
printf("\nlen: %d par_count: %d", len, par_count);
}
// Close read in parent
close(pfd[0]);
return 0;
}
Why does this change affect the return of the write
calls? I understand why it affects the read
returns - that makes sense to me. But I don't understand why this change makes the write
calls report -1. Is the return of write
dependent on the data being read by a read
call?
To answer the question in the title: No. write()
simply stores the data in the pipe buffer and returns immediately, it doesn't wait for the pipe to be read. When not -1, the return value is the number of bytes that were written to the buffer.
The problem in your code is that you have close(pfd[1])
before the loop that forks all the children. As a result, the children inherit the closed write end of the pipe, so they can't write to it.
You should move that call after the loop.
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