The final point to consider is how the child process moves from kernel mode (in which it was created) back to user mode.
18.104.22.168 Returning from fork()
When the child process is first scheduled onto a CPU the value in its EIP register is the address of the ret_from_fork routine; see Figure 8.19, from arch/i386/kernel/entry.S. This value was set up in its thread structure by the code in Section 22.214.171.124.
179 pushl %ebx
184 jne tracesys_exit
18 5 jmp ret_from_sys_call
179 at this stage, all the other registers contain values inherited from the parent. The EBX register contains a pointer to the task_struct of the parent. This is the parameter to the function called on the next line, being pushed here in preparation for the call.
180 this function, described in Section 126.96.36.199, does some cleaning up of the task_struct of its parent.
181 after returning from the call, the immediate addition of value of 4 to the ESP register discards the value pushed on the stack at line 179.
182 this macro, from Section 10.3.4, gets a pointer to the task_struct of the child process into the EBX register.
183 this checks if the child is being traced. The tsk_ptrace offset is defined in Section 10.3.5; it identifies the ptrace field of the task_struct. Bit 1 in this field is the PT_TRACESYS bit (see Figure 2.4, page 17). It means that the child process is being traced but is only to be interrupted at each system call.
184 if that bit was set, then the zero flag will be clear in EFLAGS, so the special code for handling traced system calls is executed (Section 10.4.3.3). This merely lets the tracer know that the child is exiting the fork() system call before jumping to ret_from_sys_call.
185 otherwise, the standard entry from a system call is taken (Section 10.6.1). This starts the execution of the child process.
The function shown in Figure 8.20, from kernel/sched.c, is only a wrapper around a call to the_schedule_tail() function, as described in Section 7.5.4. It is always the first code executed by a process when it wakes up after a context switch. It does some cleaning up of the task_struct of the previous process, in this case of its parent.
534 asmlinkage void schedule_tail(struct task_struct *prev)
Figure 8.20 Cleaning up after the parent
Was this article helpful?