Search code examples
c++linuxpipeipcsystems-programming

What is related and unrelated processes?


Can someone please clarify the definition of related and unrelated processes?

I know that fork creates two related processes

fork()

However, I am not sure whether the process is still considered related when we call exec* family functions to replace program image:

if (child) {
   exec("path to binary", ...) <- Is it still related process
}

The reason I am asking is to clarify which IPC method can be used in which scenario. For instance, pipes are only allowed between related processes. So I am asking above to clarify whether new program that I wrote, probably with different language, can access to the pipe file descriptors or not.

Can we say that any process created with fork() regardless of whether exec or original program image is used is always related and all others are unrelated?

Thanks!

ref: mark mitchell: advanced linux programming

A call to pipe creates file descriptors, which are valid only within that process and its children. A process’s file descriptors cannot be passed to unrelated processes; however, when the process calls fork, file descriptors are copied to the new child process.Thus, pipes can connect only related processes.


Solution

  • Can we say that any process created with fork() regardless of whether exec or original program image is used is always related?

    Yes, we can.

    Regardless of whether you call exec in child, parent and child processes can still talk to each other using pipes. See below example of creating child process, which will change itself into echo and then parent can still read its echo argument.

    #include <iostream>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <assert.h>
    
    int main() {
    
      int filedes[2];
      int const pipeRes = ::pipe(filedes);
      assert(pipeRes != -1) ;
    
      pid_t pid = ::fork();
      assert(pid != -1);
    
      if (pid == 0) // child code                                                                                                                                                                                                               
        {
          // connect the entrance of the pipe to STDOUT_FILENO within the child process                                                                                                                                                         
          while ((::dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
          // close both input and output of new pipe in child process                                                                                                                                                                           
          close(filedes[1]);
          close(filedes[0]);
          execl("/bin/echo", "echo", "child-says-hello", (char*)0);
          assert(false); // execl failed                                                                                                                                                                                                        
        }
    
      // parent code                                                                                                                                                                                                                            
      close(filedes[1]); // close input of new pipe in parent, it will only read from it                                                                                                                                                        
    
      char buffer[1024];
      while (1)
        {
          ssize_t count = read(filedes[0], buffer, sizeof(buffer));
          if (count == -1)
            {
              if (errno == EINTR) continue;
              else assert(false);
            }
          else if (count == 0)
            {
          // read everything                                                                                                                                                                                                                
              break;
            }
          else
            {
              std::cout << "received count:" << count << " bytes with: " << buffer << "\n";
            }
        }
    
      close(filedes[0]);
      wait(0);
      return 0;
    }
    

    The output is

    eceived count:17 bytes with: child-says-hello
    

    Code example above was based on this tutorial.