create a details tutor about this"Multiple processes
Processes can create their own processes—called child processes—through appropriate system calls, such as fork() or spawn(); this process is called spawning. Child processes are
independent forks of the main process with a separate memory address space, which again
means the process works independently and is isolated from others by the OS’s control. It
cannot directly access the data of other processes, and instructions belonging to each process are executed in the corresponding process independently and, ideally, in parallel.
Now we are moving into the territory of concurrency. Using spawning programs, execution can be decomposed into multiple processes that can be executed simultaneously
on parallel hardware.
However, this is probably easier to understand in code than in theory. Here is an example
of a program that makes three child processes using a forking mechanism:
# Chapter 4/child_processes.py
import os
from multiprocessing import Process
def run_child() -> None:
 print(“Child: I am the child process”)
 print(f”Child: Child’s PID: {os.getpid()}”)
 print(f”Child: Parent’s PID: {os.getppid()}”)
62 Chapter 4 I Building blocks of concurrency
def start_parent(num_children: int) -> None:
 print(“Parent : I am the parent process”)
 print(f”Parent : Parent’s PID: {os.getpid()}”)
 for i in range(num_children):
 print(f”Starting Process {i}”)
 Process(target=run_child).start()
if __name__ == “__main__”:
 num_children = 3
 start_parent(num_children)
The code creates a parent process with three child processes that are copies of the parent
process; the only difference is the process ID. The execution of the parent and child processes is independent.
NOTE It’s important to note that when forking a process, the new process
starts its execution from the point where the forking occurred, and its internal
state is copied. It does not execute the script again from the beginning.
The program outputs messages from the parent and child processes with their respected
PIDs, similar to the following:
Parent : I am the parent process
Parent : Parent’s PID: 73553
Parent : Child’s PID: 73554
Child: I am the child process
Child: Child’s PID: 73554
Child: Parent’s PID: 73553
Parent : I am the parent process
Parent : Parent’s PID: 73553
Parent : Child’s PID: 73555
Child: I am the child process
Child: Child’s PID: 73555
Child: Parent’s PID: 73553
Parent : I am the parent process
Parent : Parent’s PID: 73553
Parent : Child’s PID: 73556
Child: I am the child process
Child: Child’s PID: 73556
Child: Parent’s PID: 73553
Programming languages commonly have high-level abstractions or service methods for
working with processes as they are easier to maintain and follow in the program source code.
Spawns a new process.
The start() method starts
the run_child function in
a separate process.
Threads 63
NOTE This forking/spawning approach has been implemented in prefork
mode in several popular server technologies. Preforking means a server
creates forks at server startup, which then handle incoming requests. NGINX,
Apache HTTP Server, and Gunicorn work in this mode, allowing them to
handle hundreds of requests. But these solutions also support other methods.
"