Forked process, thread and address spaces little deeper
Will be exploring what happens in linux forking and thread creation using pthread
In Fork() call
- The child process has a unique process ID.
- The child process has a different parent process ID (i.e., the process ID of the parent process).
- The child process has its own copy of the parent’s descriptors. These descriptors reference the same underlying objects, so that, for instance, file pointers in file objects are shared between the child and the parent, so that an lseek(2) on a descriptor in the child process can affect a subsequent read(2) or write(2) by the parent. This descriptor copying is also used by the shell to establish standard input and output for newly created processes as well as to set up pipes.semaphores if opened it also inherit. Memory mappings created in the parent are retained in the child process,(If MAP_PRIVATE was used in parent,it will be MAP_PRIVATE in child to, after forking if any change in memory mapped area that will be visible to corresponding process only)
- The child process’ resource utilizations are set to 0; see setrlimit.
- All interval timers are cleared;.
Here process is created with a single thread. If a multi-threaded process calls fork()
, the new process contains a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal safe operations until such time as one of the exec
functions is called. Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork()
calls.
In summery
The child gets an exact copy of the parents address space, which in many cases is likely to be laid out in the same format as the parent address space. I have to point out that each one will have it’s own virtual address space for it’s memory, such that each could have the same data at the same address, yet in different address spaces. Also, linux uses copy on write when creating child processes. This means that the parent and child will share the parent address space until one of them does a write, at which point the memory will be physically copied to the child. This eliminates unneeded copies when execing a new process. Since you’re just going to overwrite the memory with a new executable, why bother copying it?
Descriptor copied first, later some elements are initialized. Most of them are intact.
Shared Resources:
In Thread() call:
Often it is sufficient to run a partial copy of a process with the other parts shared with other processes. Such copies can be realized by a thread (an example of a lightweight process) which has the following properties:
- Resources and data can be shared between threads
- Each thread has its own stack
- Context switching is fast
A fork()
induces a parent-child relationship between two processes. Thread creation induces a peer relationship between all the threads of a process.
- The
main()
thread runs first, but has no other priority - The main thread may have some special properties
Processes and threads can
- Terminate
- Start a new process or thread
- Wait for each other to terminate
- Terminate each other
- Share data and communicate
- Run independently