-1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#define LG_LIGNE 256
int main(void){

char ligne[LG_LIGNE];
while(1){//afficher un symbole d'invite(prompt)
    fprintf(stderr, "-->");
    //lire une ligne de commandes
    if(fgets(ligne,LG_LIGNE,stdin)==NULL)
    break;
    //supprimer le retour chariot final
    ligne[strlen(ligne)-1]='\0';
    //lancer un processeur
    if(fork()==0){
    //processus fils
    //executer la commande
    execlp(ligne, ligne, NULL);
    //msg d'erreur si on echoue
    perror(ligne);
    exit(EXIT_FAILURE);
    }
    else{//process père
    //attendre la fin de son fils
    waitpid(-1,NULL,0);
    //et reprendre la boucle
    }
}
fprintf(stderr,"\n");
return EXIT_SUCCESS;
}

I understand what each return value means but I didn't quite understand it here, what being in the child/father process technically means, and I couldn't see the use of waitpid, what will happen if I didn't use it?

flora
  • 47
  • 5

2 Answers2

3

Fork() creates a copy of the process's memory and state, and spawns a child process to run in it. Both the child and parent run in their own process, with their own copy of the address space and virtual memory. So how can you tell which is the parent and which is the child since both tasks resume execution after the fork() call with identical state and memory?

You can tell which is the parent and which is the child based on the return code from fork(). If the return value is zero, then you are the child process, and this process usually tests the return code for zero, and branches off to do the child's work.

Meanwhile, the parent also returns from the same fork() call but with the return code set to the process id of its child (which is non-zero). The parent may choose to save this process id, but it is only really useful if the parent is creating multiple children and wants to track them through their process ids.

Before the parent finishes, it typically waits for its child processses to complete first. This is what the waitpid call does. You can pass in the child process's id, in which case the waitpid call does not return until that child process completes. Passing -1 into waitpid tells it to wait until ONE of your child tasks completes.

The return code from waitpid contains the process id of the child task that completed. For more information, this has already been answered here https://stackoverflow.com/a/21249082/6693299

For a complete explanation of what your program does, read the excellent detailed description by H.S. that answers the same question here https://stackoverflow.com/a/46741392/6693299

ScottK
  • 1,526
  • 1
  • 16
  • 23
1

Your first question -

what being in the child/father process technically means

The fork() creates a child process by duplicating the calling process. The process that invoked fork() is the parent process and the newly created process is the child process. So fork() splits a process in two, and returns 0 to the child process and the PID of the child process to the parent process, or -1 if the fork failed.

The child process and the parent process run in separate memory spaces. At the time of fork() both memory spaces have the same content.

There is concept called Copy on Write, its good to have knowledge about it-

Copy on Write is an optimization where the page tables are set up so that the parent and child process start off sharing all of the same memory, and only the pages that are written to by either process are copied when needed.

If the process does not modify any memory and immediately executes a new process, replacing the address space entirely. Thus, it would be wasteful to copy all of the process's memory during a fork, and instead the copy-on-write technique is used.

For example, in your program you have immediately calling execlp after fork:

if(fork()==0){
//processus fils
//executer la commande
execlp(ligne, ligne, NULL);

Your second question -

I couldn't see the use of waitpid, what will happen if I didn't use it?

To explain this, I have modified your program and added statement to print parent and child process pid's and commented out this statement-

waitpid(-1,NULL,0);

Output of program is -

parent process pid : 22325 -->ls child process pid : 22326 < here the output of ls command >

Now, if we see the output of ps command with grep'ed parent process id -

# ps -eaf | grep 22325
root     22325 21555  0 10:39 pts/4    00:00:00 ./a.out
root     22326 22325  0 10:39 pts/4    00:00:00 [ls] <defunct>
root     22339 21644  0 10:39 pts/5    00:00:00 grep 22325

Here, in the output the first column is UID, second is PID and third id PPID (parent pid). You can see the child process (pid - 22326) is marked as < defunct >.

A "defunct" process (also referred to as "zombie" process) is a process which has finished execution, it will have an exit status to report to its parent process. Because of this last little bit of information, the process will remain in the operating system’s process table as a zombie process, indicating that it is not to be scheduled for further execution, but that it cannot be completely removed (and its process ID cannot be reused) until it has been determined that the exit status is no longer needed.

And here comes the use of waitpid() -

The wait() and waitpid() functions shall obtain status information pertaining to one of the caller's child processes.

waitpid() suspends the calling process until the system gets status information on the child. If the system already has status information on an appropriate child when waitpid() is called, waitpid() returns immediately. waitpid() is also ended if the calling process receives a signal whose action is either to execute a signal handler or to end the process.

For other details on waitpid() like syntax (status, options) and return value you can check its man page.

If I uncomment the waitpid() in your program and compile and run it, the output -

parent process id : 23069
-->ls
child process id : 23070
<here the output of ls command>

Now, if we see the output of ps command with grep'ed parent process id -

# ps -eaf | grep 23069
root     23069 21555  0 10:51 pts/4    00:00:00 ./a.out
root     23108 21644  0 10:51 pts/5    00:00:00 grep 23069

There is no zombie process. The child process which runs ls command has been finished and the parent process read its exit status.

Hope this answer your both the questions.

Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
H.S.
  • 11,654
  • 2
  • 15
  • 32