I have to write program that create process using pipe()
.
My first task is to write a parent process that generates four child processes using the fork()
function.
Once the fork()
is successful, replace the child process with another process rover1, rover2, rover3, and rover4
, though all of them have the same code.
The function of the processes is as follows.
Each child process is initially given its own number. It receives a new number from the parent. Using the following formula it creates its own new number as follows and forwards it to the parent:
mynumber = (3 * mynumber + 4 * numberreceived)/7
This process continues until the parent sends the message that the system is stable. The parent also has its initial number. It receives numbers of all the children and computes its new number as follows:
mynumber = (3 * mynumber + numbers sent by all the children)/7
The parent will send this number to all its children. This process will continue until the parent finds that its number is not changing anymore. At that time it will tell the children the system has become stable.
This is what I did but my professor said I have to use exec() to execute the child and replace child process with another child process. I am not sure how to use exec(). Could you please help me with this.
I am attaching only first child generation.
// I included stdio.h, unistd.h stdlib.h and errno.h
int main(void)
{
// Values returned from the four fork() calls
pid_t rover1, rover2, rover3, rover4;
int parentnumber, mynumber1, mynumber2, mynumber3, mynumber4;
int childownnumber1 = 0, status = 1, childownnumber2 = 0,
childownnumber3 = 0, childownnumber4 = 0, numberreceived = 0;
printf("Enter parent number: ");
printf("%d", parentnumber);
printf("Enter each children number");
printf("%d %d %d %d", mynumber1, mynumber2, mynumber3, mynumber4);
// Create pipes for communication between child and parent
int p1[2], p2[2];
// Attempt to open pipe
if (pipe(p1) == -1) {
perror("pipe call error");
exit(1);
}
// Attempt to open pipe
if (pipe(p2) == -1) {
perror("pipe call error");
exit(1);
}
// Parent process generates 4 child processes
rover1 = fork();
// if fork() returns 0, we're in the child process;
// call exec() for each child to replace itself with another process
if (rover1 == 0) {
for(; numberreceived != 1; ) {
close(p1[1]); // Close write end of pipe
close(p2[0]); // Close read end of second pipe
// Read parent's number from pipe
read(p1[0], &numberreceived, sizeof(int));
if (numberreceived == 1) {
// System stable, end child process
close(p1[0]);
close(p2[1]);
_exit(0); // End child process
}
mynumber1 = (int)((3*mynumber1 + 4*numberreceived)/7.0);
printf("\nrover1 number: ");
printf("%i", mynumber1);
// Write to pipe
write(p2[1], &mynumber1, sizeof(int));
}
}
/* Error:
* If fork() returns a negative number, an error happened;
* output error message
*/
if (rover1 < 0) {
fprintf(stderr,
"can't fork, child process 1 not created, error %d\n",
errno);
exit(EXIT_FAILURE);
}
}
If you are supposed to use
exec
, then you should split your program into two binaries.Basically, the code that now gets executed by the child should be in the second binary and should be invoked with
exec
.Before calling one of the
exec
family of functions, you'll also need to redirect the pipe descriptors to the new process' standard input/output usingdup2
. This way the code in the second binary that getsexec
'd won't be aware of the pipe and will just read/write to the standard input/output.It's also worth noting that some of the data you are using now in the child process is inherited from the parent through the
fork
. When usingexec
the child won't share the data nor the code of the parent, so maybe you can consider transmitting the needed data through the pipe as well.The
exec
family of functions is used to replace the current process with a new process. Note the use of the word replace. Once exec is called, the current process is gone and the new process starts. If you want to create a separate process, you must firstfork
, and thenexec
the new binary within the child process.Using the
exec
functions is similar to executing a program from the command line. The program to execute as well as the arguments passed to the program are provided in the call to theexec
function.For example, the following
exec
command* is the equivalent to the subsequent shell command:execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
/bin/ls -r -t -l
* Note that "arg0" is the command/file name to execute
Since this is homework, it is important to have a good understanding of this process. You could start by reading documentation on
pipe
,fork
, andexec
combined with a few tutorials to gain a better understanding each step.The following links should help to get you started: