Author: handi Thursday, October 28, 2004
Read the core diary fork
In the middle of the information and article, I will also list this one by one by the diary 1. Lion's UNIX source code analysis 2. Kernel 2.6.8 /kernel/fork.c3. Kernel 2.4.18 /kernel/fork.c4. Linux scenario analysis (upper, bottom)
Basically, no functions named by fork, but also comply with Match Case and Match Whold Word ONLY
So Sys_Fork -> do_fork, just like SOCKET, only sys_socket is forfell () and socket () when the system is called, I think it may be the reason for the function Map.
Let's talk about the general process, then explain the code first, check some states, get some necessary information -> Enter the COPY_PROCESS entity, copy the process (there is a very important point in the middle, is why the child process returns 0) -> Set some information -> Let the process start Run
Compared to UNIX, I can only say that Linux is really complicated and Luo Wei. The implementation in Lion's Unix is very simple and clear. If you just want to understand the principle, the FORK is enough, and very honest, no sys_fork, v_fork, DO_FORK, nested, just a fork
Of course, I don't know how this is implemented in UNIX version, so I will find some code implemented in Minix or BSD for reference, and then add to the diary.
The front is so much, or let's analyze the source code ./kernel/fork.c
KERNEL_THREAD (), SYS_FORK (), SYS_CLONE (), SYS_VFORK () These various functions are calling the do_fork () function, the main parameters are concentrated on Clone_Flags, on /arch/i386/kernel/process.c
/ * * Ok, this is the main fork-routine. * * It copies the process, and if successful kick-starts * it and waits for it to finish using the VM if required. * / Long do_fork (unsigned long clone_flags, / * Clone logo * / unsigned long stack_start, / * Stack starting position - how do you not need a pointer? * / Struct pt_regs * regs, / * register * / unsigned long stack_size, / * stack size * / int __user * Parent_tidptr, / * Father What pointer to the process * / int __User * child_tidptr) / * What pointer does the child process? * / {Struct task_struct * p; / * PCB structure * / int track = 0; long pid;
/ * Clone_ptrace This macro said in what is the meaning on the child to let tracing continue on the child TOO] * Translated means that if you want to track the sub-process, set this bit * whether tracking by Do_Fork's parameter clone_flags determined * That means that the information of the tracking sub-process is determined by us when calling * /
/ * CURRENT This refers to the current parent process? * Unlikely prototype: * #include
P = copy_process (clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tiDPTR);
/ * * Do this prior WAKING UP THE New Thread - The Thread Pointer * Might Get Invalid After That Point, IF The Thread EXITS Quickly. * / PID = IS_ERR (P)? PTR_ERR (P): P-> PID;
/ * Process replication success * / if (! Is_err (p)) {struct completion vfork;
IF (clone_flags & clone_vfork) {p-> vFork_done = & vfork; init_completion (& vfork);}
if ((p-> ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {/ * * We'll start up with an immediate SIGSTOP * / sigaddset (& p-> pending.signal, SIGSTOP);. set_tsk_thread_flag (p, TiF_sigpending);
if (! (clone_flags & CLONE_STOPPED)) {/ * * Do the wakeup last. On SMP we treat fork () and * CLONE_VM separately, because fork () has already * created cache footprint on this CPU (due to * copying the pagetables .), hence migration would * probably be costy Threads on the other hand * have less traction to the current CPU, and if * there's an imbalance then the scheduler can * migrate this fresh thread now, before it * accumulates a larger cache footprint: * / / * new fork wakeup process * / if (clone_flags & CLONE_VM) wake_up_forked_thread (p); else wake_up_forked_process (p);} else {int cpu = get_cpu (); p-> state = TASK_STOPPED; if (cpu_is_offline (task_cpu (p)))) SET_TASK_CPU (P, CPU);
PUT_CPU (); Total_Forks;
IF (unlikely (trarent) {current-> ptrace_message = pid; ptrace_notify ((Trace << 8) | SigTrap);}
if (clone_flags & CLONE_VFORK) {wait_for_completion (& vfork); if (unlikely (current-> ptrace & PT_TRACE_VFORK_DONE)) ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);} else / * * Let the child process run first, to avoid MOST OF THE * COW OVERHEAD WHEN THE CHILD EXEC () s afterwards. * / / * Let the child process run * / set_need_resched ();} return pid;}