System
call fork() is used to create processes. It takes no arguments
and returns a process ID.The purpose of fork() is to create
a new process, which becomes the child process
of the caller. After a new child process is created, both processes
will execute the next instruction following the fork() system
call. Therefore, we have to distinguish the parent from the child. This can be
done by testing the returned value of fork():
- If fork() returns a negative value,
the creation of a child process was unsuccessful.
- fork() returns
a zero to the newly created child process.
- fork() returns a positive value, the process
ID of the child process, to the parent. The returned process
ID is of type pid_t defined in sys/types.h.
Normally, the process ID is an integer. Moreover, a process can use
function getpid() to retrieve the process ID assigned to
this process.
Therefore, after the system call
to fork(), a simple test can tell which process is the child. Please
note that Unix will make an exact copy of the parent's address space
and give it to the child. Therefore, the parent and child processes
have separate address spaces.
Let
us take an example to make the above points clear. This example does not distinguish
parent and the child processes.
#include <stdio.h>
#include <string.h>
#include
<sys/types.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void)
{
pid_t pid;
int i;
char buf[BUF_SIZE];
fork();
pid = getpid();
for (i = 1; i <=
MAX_COUNT; i++)
{
sprintf(buf, "This
line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));
}
}
if the call to fork() is
executed successfully, Unix will
- make two identical copies of address spaces, one for
the parent and the other for the child.
- Both processes will start their
execution at the next statement following the fork() call.
In this case, both processes will start their execution at the assignment
statement pid=getpid()
Consider
one more simple example, which distinguishes the parent from the child.
#include
<sys/types.h>
#define MAX_COUNT 200
void
ChildProcess(void); /* child
process prototype */
void
ParentProcess(void); /* parent
process prototype */
void main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
}
void ChildProcess(void)
{
int i;
for (i = 1; i <=
MAX_COUNT; i++)
printf("
This line is from child, value = %d\n", i);
printf(" *** Child process is done ***\n");
}
void ParentProcess(void)
{
int i;
for (i = 1; i <=
MAX_COUNT; i++)
printf("This
line is from parent, value = %d\n", i);
printf("*** Parent
is done ***\n");
}
In this program, both processes print lines that indicate whether
the line is printed by the child or by the parent process, and the value of
variable i. For simplicity, printf() is used.
When the main program executes fork(), an
identical copy of its address space, including the program and all data, is
created. System call fork() returns the child process ID to
the parent and returns 0 to the child process. The following figure shows that
in both address spaces there is a variable pid. The one in the
parent receives the child's process ID 3456 and the one in the child receives
0.
Due to the fact that
the CPU scheduler will assign a time quantum to each process, the parent or the
child process will run for some time before the control is switched to the
other and the running process will print some lines before you can see any line
printed by the other process. Therefore, the value of MAX_COUNT should be
large enough so that both processes will run for at least two or more time
quanta. If the value of MAX_COUNT is so small that a process can finish in one time
quantum, you will see two groups of lines, each of which contains all lines
printed by
Comments
Post a Comment