简体   繁体   中英

Using pipe() and fork() to read from a file and output to the console/new file

I'm trying to learn how to use the pipe() and fork() system calls. I'm using pipe and fork to create parent and child processes where the child will read a character from the text file, and then send it through the pipe to the parent that will then output the character to the console, with the desired result that it will print out the entire text to the console. Later I'm going to be doing some text processing on the file with the child process reading and processing then sending the updated text to the parent but for now I just want to make sure I'm getting the basics of pipe() correct.

example file:

This is a test file; it is 1 of many.
Others will follow. 

Relevant code:

  pid = fork();

  ifstream fin;
  fin.open(inputFilename);
  fin.get(inputChar);

  if (pid == -1)
  {
    perror("Trouble");
    exit(2);
  }
  else if (pid == 0) //child process that reads text file and writes to parent
  {
    close(pipefds[0]);
    while(!fin.eof())
    {
      write(pipefds[1], &inputChar, sizeof(inputChar));
      fin.get(inputChar);
    }

    close(pipefds[1]);

    exit(0);
  }
  else
  {
    close(pipefds[1]);
    read(pipefds[0], readbuffer, sizeof(readbuffer));
    cout << readbuffer << endl;
    close(pipefds[0]);
    exit(0);

  }
      fin.close();

However, when I compile and run, the output is always of a varying length. Sometimes it will print the whole file, others it will just print out a few letters, or half of a line. Such as.

This i

I've tried going through the man pages and researching more but I haven't been able to find any answers. What exactly is going on with my program that it will sometimes read everything from the file but other times won't. Any help is greatly appreciated!

It looks as though you're trying to read all the data from the pipe with one call to read(2) . But, as with any I/O operation, this may always return fewer bytes than you requested. You should always check the return value of read(2) and write(2) system calls (and others), to make sure that they acted as expected.

In this case, you should loop until you get some independent notification from the child process that they're done sending data. This can be signaled in this case by read(2) returning 0 , meaning that the child closed their end of the pipe.

You are assuming that the parent can read everything written to the pipe by the child via one read() call. That might be a safe assumption for a pipe if the child were writing everything via a single write() call, as long as the overall data size did not exceed the size of the pipe's internal buffer. It is not at all safe when, as in this case, the child is sending data via many little writes.

How much data the parent actually gets will depend in part on how its one read() call is ordered relative to the child's writes. Inasmuch as the two are separate processes and you're employing no IPC other than the pipe itself, it's basically unpredictable how much data the parent will successfully read.

In the general case, one must assume that the reader will need to perform multiple read() calls to read all data that are sent. It must keep calling read() and processing the resulting data appropriately until read 's return value indicates that an I/O error has occurred or that the end of the file has been reached. Note well that end of file does not mean just that no more bytes are available now , but that no more bytes will ever be available. That happens after all processes have closed all copies of the write end of the pipe.

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