2

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.

Validus Oculus
  • 2,756
  • 1
  • 25
  • 34
  • 1
    `all others are unrelated?` All processes are created from PID 1 => All processes are "related" – KamilCuk Aug 18 '20 at 05:45
  • 1
    Calling `fork()` creates a child process that is identical to the original. Calling `exec()` doesn't change the relationship between the two processes - the child/parent relationship is unaffected. However, if the parent created the pipes and marked them "close on exec", then the child calling `exec()` will cause the pipes to be closed. – Peter Aug 18 '20 at 05:47

1 Answers1

2

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.

Łukasz Ślusarczyk
  • 1,775
  • 11
  • 20