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.
-
#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 as shown below:
Both processes start their execution right after the system call fork(). Since both processes have identical but separate address spaces, those variables initialized before the fork() call have the same values in both address spaces. Since every process has its own address space, any modifications will be independent of the others. In other words, if the parent changes the value of its variable, the modification will only affect the variable in the parent process's address space. Other address spaces created by fork() calls will not be affected even though they have identical variable names.
What is the reason of using write rather than printf? It is because printf() is "buffered," meaning printf() will group the output of a process together. While buffering the output for the parent process, the child may also use printf to print out some information, which will also be buffered. As a result, since the output will not be send to screen immediately, you may not get the right order of the expected result. Worse, the output from the two processes may be mixed in strange ways. To overcome this problem, you may consider to use the "unbuffered" write.
If you run this program, you might see the following on the screen:
................ This line is from pid 3456, value 13 This line is from pid 3456, value 14 ................ This line is from pid 3456, value 20 This line is from pid 4617, value 100 This line is from pid 4617, value 101 ................ This line is from pid 3456, value 21 This line is from pid 3456, value 22 ................
#include <stdio.h> #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"); }