Both parent and child return different values due to manipulation of the processor register in the child context.
Each process in the linux kernel is represented by task_struct. task_struct is wrapped (pointer) in the thread_info structure, which is located at the end of the kernel mode stack. This thread_info structure stores an empty processor context (registers).
struct thread_info { struct task_struct *task; struct cpu_context_save cpu_context; }
All fork / clone () system calls invoke the do_fork () kernel equivalent function.
long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr)
Here is the execution sequence
do_fork () → copy_process-> copy_thread () (copy_thread is a function call of a special function)
copy_thread () copies the register values from the parent element and changes the return value to 0 (In the case of a hand)
struct pt_regs *childregs = task_pt_regs(p); *childregs = *regs; childregs->ARM_r0 = 0; thread->cpu_context.sp = (unsigned long)childregs; thread->cpu_context.pc = (unsigned long)ret_from_fork;
When the child receives the scheduled task, he performs the assembly procedure ret_from_fork (), which returns zero. For the parent, it gets the return value from do_fork (), which is the process pid
nr = task_pid_vnr(p); return nr;
sysinit May 23 '14 at 2:10 2014-05-23 02:10
source share