简体   繁体   中英

pipe examples between child and parent in Linux C

This looks really simple, a pipe between, parent will write to a pipe at write end of the pipe, and the child will read from the pipe in a while loop, and print what has read, but my program failed to stop...

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int
main(int argc, char *argv[]){
  int fd[2];
  int number;
  int write_number[1];
  pipe(fd);
  int pid;
  if ((pid = fork()) >0){
     close(fd[0]);
     for (int i = 2; i < 36; i++){
         *write_number = i;
         write(fd[1], write_number, 4);
     }
     printf("write finished from parent process:%d\n", pid);
     close(fd[1]);
  }else{// child process
     close(fd[1]);
     while(read(fd[0], &number, 4))
        printf("The number is %d from child %d\n", number, getpid());
     close(fd[0]);
  }
  exit(0);
}

by the way, this is from xv6 Unix-like system, but I assume this is almost the same as in Linux, the output:

$ primes
The numbwerite finished from parent prorc eis ss:24
 from $ child 4
The number is 3 from child 4
The number is 4 from child 4
The number is 5 from child 4
The number is 6 from child 4
The number is 7 from child 4
The number is 8 from child 4
The number is 9 from child 4
The number is 10 from child 4
The number is 11 from child 4
The number is 12 from child 4
The number is 13 from child 4
The number is 14 from child 4
The number is 15 from child 4
The number is 16 from child 4
The number is 17 from child 4
The number is 18 from child 4
The number is 19 from child 4
The number is 20 from child 4
The number is 21 from child 4
The number is 22 from child 4
The number is 23 from child 4
The number is 24 from child 4
The number is 25 from child 4
The number is 26 from child 4
The number is 27 from child 4
The number is 28 from child 4
The number is 29 from child 4
The number is 30 from child 4
The number is 31 from child 4
The number is 32 from child 4
The number is 33 from child 4
The number is 34 from child 4
The number is 35 from child 4

it does not stop, so it hangs, but I've close the file descriptor I should close, so the read system call should return 0 if nothing read, why it is still hanging, so anyone could give me a hand? thanks!

It did stop — the parent exited and produced the prompt from the shell in the messed up output before the child printed "The number is 3 from the child 4":

$ primes
The numbwerite finished from parent prorc eis ss:24
 from $ child 4
The number is 3 from child 4

You should probably have the parent process wait in a loop with the wait() or waitpid() function so that the child completes before the parent exits and the shell reprompts.

#include <sys/wait.h>

…

int status;
int corpse;
while ((corpse = wait(&status)) > 0)
    print("Child %d died with exit status 0x%.4X\n", corpse, status);

Although it's very unlikely, it is possible for a process to have children that the current program didn't fork — and the loop works correctly for that case too.

Tangential notes:

  1. Since you ignore the command line arguments, it would be better to use int main(void) .

  2. The exit(0); is not necessary. You could omit it and, if you compile in C99 or later mode, the process will exit with zero. That's a special-case rule for the main() function only. Personally, I prefer to use an explicit return 0; at the end of main() .

  3. You have:

     for (int i = 2; i < 36; i++){ *write_number = i; write(fd[1], write_number, 4); }

You could use:

    for (int i = 2; i < 36; i++)
        write(fd[1], &i, sizeof(i));

Using sizeof() is idiomatic; use 4 is error-prone. And there's no need for the write_number array.

  1. The choice of headers is conventional. You should be using <stdio.h> , <unistd.h> , and <sys/wait.h> . You don't actually need <sys/types.h> . The kernel headers should only be used when compiling code to run in the kernel — this program is not kernel code.

You say:

I added some code like printf("child process is finished"), in the child condition, it print, but without wait(0) before exit(0), it means child process is no problem, it will wait from the pipe to close, but at the end the program does not finish, just hangs there seem waiting for input, I thought this is the case where parent exit but not waiting for the child to exit(), but the child does exit at the end, but he program does NOT finish....very last confusion

IMO, your code should look like:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    int fd[2];
    pipe(fd);
    int pid;
    if ((pid = fork()) > 0)
    {
        close(fd[0]);
        for (int i = 2; i < 36; i++)
            write(fd[1], &i, sizeof(i));
        close(fd[1]);
        printf("write finished from parent process:%d\n", pid);
        int status;
        int corpse;
        while ((corpse = wait(&status)) > 0)
        {
            printf("%d: child %d exited with status 0x%.4X\n",
                   (int)getpid(), corpse, status);
        }
    }
    else if (pid < 0)
    {
        fprintf(stderr, "failed to fork\n");
        return 1;
    }
    else
    {
        int number;
        close(fd[1]);
        while (read(fd[0], &number, sizeof(number)) > 0)
            printf("The number is %d from child %d\n", number, getpid());
        close(fd[0]);
    }
    return 0;
}

One example output I got (run on a MacBook Pro running macOS Big Sur 11.2.3) was:

write finished from parent process:53072
The number is 2 from child 53072
The number is 3 from child 53072
The number is 4 from child 53072
The number is 5 from child 53072
The number is 6 from child 53072
The number is 7 from child 53072
The number is 8 from child 53072
The number is 9 from child 53072
The number is 10 from child 53072
The number is 11 from child 53072
The number is 12 from child 53072
The number is 13 from child 53072
The number is 14 from child 53072
The number is 15 from child 53072
The number is 16 from child 53072
The number is 17 from child 53072
The number is 18 from child 53072
The number is 19 from child 53072
The number is 20 from child 53072
The number is 21 from child 53072
The number is 22 from child 53072
The number is 23 from child 53072
The number is 24 from child 53072
The number is 25 from child 53072
The number is 26 from child 53072
The number is 27 from child 53072
The number is 28 from child 53072
The number is 29 from child 53072
The number is 30 from child 53072
The number is 31 from child 53072
The number is 32 from child 53072
The number is 33 from child 53072
The number is 34 from child 53072
The number is 35 from child 53072
53069: child 53072 exited with status 0x0000

If the output was piped to another program, the " write finished from parent process:53072 " line appeared at the end before the "exited" printing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM